代码之家  ›  专栏  ›  技术社区  ›  Pete

Java在运行时加载用户指定的类

  •  3
  • Pete  · 技术社区  · 16 年前

    我正在用Java(Swing应用程序)进行机器人仿真。我有一个抽象类“Robot”,从中派生出不同类型的机器人。

    public class StupidRobot extends Robot {
       int m_stupidness;
       int m_insanityLevel;
       ...
    }
    
    public class AngryRobot extends Robot {
       float m_aggression;
       ...
    }
    

    如您所见,每个Robot子类都有一组不同的参数。

    我想做的是在初始UI中控制模拟设置。选择机器人的数量和类型,给它一个名字,填写参数等。

    作为一个恐龙程序员,又是Java新手,我想知道是否有更高层次的东西/想法可以帮助我。我得到的是:

    (1) 用户界面

    右侧默认命名的机器人滚动列表。 下面的“设置参数”按钮。 (因此,如果您想要AngryRobot,您可以在左侧列表中选择AngryRobot,单击“添加”>&燃气轮机“愤怒机器人1”会出现在右边。)

    选择右侧的机器人时,单击“设置参数…”按钮,这将调用另一个模型对话框,您可以在其中填写参数。为每个调用不同的对话框 机器人类型。

    (2) 数据结构与实现

    enum ROBOT_TYPE {STUPID, ANGRY, etc}
    
    public class RobotInitializer {
        public ROBOT_TYPE m_type;
        public string m_name;
        public int[] m_int_params;
        public float[] m_float_params;
        etc.
    

    初始值设定项的构造函数将基于以下类型创建适当的长度参数数组:

    public RobotInitializer(ROBOT_TYPE type, int[] int_array, float[] float_array, etc){
         switch (type){
            case STUPID:
                m_int_params = new int[STUPID_INT_PARAM_LENGTH];
                System.arraycopy(int_array,0,m_int_params,0,STUPID_INT_PARAM_LENGTH);
    
            etc.
    

    一旦所有robotInitializer都被实例化,它们就会被添加到HashMap中。

    在HashMap中迭代,模拟初始值设定项从HashMap中获取项目,并实例化相应的机器人。

    这合理吗?如果没有,如何改进?

    谢谢

    3 回复  |  直到 16 年前
        1
  •  1
  •   matiasf    16 年前

    如前所述,可以将Robot作为RobotInterface的实现。然后:

    Class aRobotClass = Class.forName("robotClassName"); //or similar
    Class[] aRobotClassImplements = aRobotClass.getIterfaces();
    // Then ensure that "RobotInterface" exists in the aRobotClassImplements array.
    

    我假设eash机器人可以有一系列不同的属性。可以动态检查Robot实例并创建适当的按钮/控制器。例如:

    Field[] robotFields = aRobotClass.getFields();
    
    for (Field field : robotFields) {
       JButton jbutton = new JButton(field.getName());
       //assuming this class implements ActionListener
       jbutton.addActionListener(this);
       // Then assume we have a private class representing a button )
       this.hashMapOrVectorOfButtons.add(new PrivateButton(field));
       jpanel.add(jbutton);
       // etc etc
    }
    

    稍后在actionPerformed中,对已注册按钮的hashmap或vector进行循环(field.getName().equals(actionEvent.getActionCommand())。然后在Robot实例中操纵适当的字段。

        2
  •  3
  •   Fede    16 年前

    可以使用反射在运行时动态加载类型。看到了吗 Class.forName 看看你怎样才能得到一个 Class 因为它是完全限定名。然后可以使用isAssignableFrom方法检查该类是否是Robot的子类。您可以在Robot中定义一些模板方法,让子类指定具体的行为(例如,应该初始化哪些属性)。一旦获得了类定义,就可以使用 newInstance() getConstructors() 方法并使用所需的方法)。

    我知道在给定类文件的完整路径的情况下,还有另一种加载类定义的方法,但现在不记得是如何加载的了。

        3
  •  1
  •   aperkins    16 年前

    您也可以使用RMIClassLoader,不过如果您可以这样使用的话,我建议您使用Fede的响应。