【问题标题】:Create new object from a string in Java从Java中的字符串创建新对象
【发布时间】:2009-08-12 21:27:42
【问题描述】:

有没有办法从 Java 中的 String 变量创建一个新类?

String className = "Class1";
//pseudocode follows
Object xyz = new className(param1, param2);

另外,如果可能的话,生成的对象是否必须是 Object 类型?

可能有更好的方法,但我希望能够从 XML 文件中检索值,然后实例化以这些字符串命名的类。这些类中的每一个都实现了相同的接口并派生自同一个父类,因此我可以调用该类中的特定方法。

【问题讨论】:

    标签: java


    【解决方案1】:

    这就是你想要做的:

    String className = "Class1";
    Object xyz = Class.forName(className).newInstance();
    

    请注意,newInstance 方法不允许使用参数化构造函数。 (见Class.newInstance documentation

    如果您确实需要使用参数化构造函数,这就是您需要做的:

    import java.lang.reflect.*;
    
    Param1Type param1;
    Param2Type param2;
    String className = "Class1";
    Class cl = Class.forName(className);
    Constructor con = cl.getConstructor(Param1Type.class, Param2Type.class);
    Object xyz = con.newInstance(param1, param2);
    

    Constructor.newInstance documentation

    【讨论】:

    • 您可以使用 getConstructor 作为参数化构造函数。
    • 你是对的 Co​​deGoat,我不知道。我将编辑我的答案以反映更好的方法。
    • 我觉得用getConstuctor比用init方法好。因为使用构造函数允许分配最终字段。
    • 将第 7 行更改为:Constructor con = cl.getConstructor(new Class[] {Param1Type.class, Param2Type.class});
    • 你也应该注意如果你使用: Object xyz = Class.forName(className).newInstance();您将默默地将已检查的异常转换为未检查的异常。此答案中的更多详细信息:stackoverflow.com/a/7495850/411401
    【解决方案2】:

    是的,您可以使用反射,使用 Class.forName(name),获取构造函数并调用它,在给定字符串名称的类路径上加载一个类。我给你举个例子。

    假设我有一堂课:

    com.crossedstreams.thingy.Foo
    

    其中有一个带有签名的构造函数:

    Foo(String a, String b);
    

    我将根据这两个事实实例化该类,如下所示:

    // Load the Class. Must use fully qualified name here!
    Class clazz = Class.forName("com.crossedstreams.thingy.Foo");
    
    // I need an array as follows to describe the signature
    Class[] parameters = new Class[] {String.class, String.class};
    
    // Now I can get a reference to the right constructor
    Constructor constructor = clazz.getConstructor(parameters);
    
    // And I can use that Constructor to instantiate the class
    Object o = constructor.newInstance(new Object[] {"one", "two"});
    
    // To prove it's really there...
    System.out.println(o);
    

    输出:

    com.crossedstreams.thingy.Foo@20cf2c80
    

    那里有很多资源可以更详细地说明这一点,您应该知道,您正在引入编译器无法为您检查的依赖项 - 如果您拼错类名或其他任何内容,它会在运行时失败。 此外,在此过程中可能会抛出许多不同类型的异常。不过,这是一项非常强大的技术。

    【讨论】:

    • 问题:既然我们已经创建了Foo 的对象,那么如何使用该对象调用Foo 的公共函数呢?我们如何将其转换为 Foo 引用?
    • 您可以像对任何对象一样进行投射。 (Foo)oFoo.class.cast(o)。但是,您可能不想这样做,因为如果您知道实现类是什么,那么执行此操作将毫无意义——您可以导入它!您实际上要做的是将实现必须实现的接口转换为您导入的接口。
    【解决方案3】:

    这应该可行:

    import java.lang.reflect.*;
    
    FirstArgType arg1;
    SecondArgType arg2;
    Class cl = Class.forName("TheClassName");
    Constructor con = cl.getConstructor(FirstArgType.class, SecondArgType.class);
    Object obj = con.newInstance(arg1, arg2);
    

    您可以从那里转换为已知类型。

    【讨论】:

      【解决方案4】:

      这在 JDK7 中对我来说工作得更干净一些,而上面的答案使事情变得比从新手的角度需要的要困难一些:(假设您已将 'className' 声明为作为字符串变量传递的方法参数或更早的方法中使用此代码):

      Class<?> panel = Class.forName( className );
      JPanel newScreen = (JPanel) panel.newInstance();
      

      从这一点开始,您可以完全按照您期望的方式使用动态命名类中的属性/方法:

      JFrame frame = new JFrame(); // <<< Just so no-one gets lost here
      frame.getContentPane().removeAll();
      frame.getContentPane().add( newScreen );
      frame.validate();
      frame.repaint();
      

      当我尝试将新的“对象”类型对象 .add() 到框架时,上面其他答案中的示例导致错误。这里展示的技术给了我一个可用的对象,只需要上面那两行代码。

      不完全确定为什么会这样 - 我自己也是 Java 新手。

      【讨论】:

        【解决方案5】:

        另一个:

        import java.lang.reflect.Constructor;
        
        public class Test {
        
         public Test(String name) {
            this.name = name;
         }
        
         public String getName() {
            return name;
         }
        
         public String toString() {
            return this.name;
         }
        
         private String name;
        
         public static void main(String[] args) throws Exception {
            String className = "Test";
            Class clazz = Class.forName(className);
            Constructor tc = clazz.getConstructor(String.class);
            Object t = tc.newInstance("John");
            System.out.println(t);
         }
        }
        

        【讨论】:

          【解决方案6】:

          使用String 对象获取class 实例的示例程序。

          public class GetStudentObjectFromString
          {
              public static void main (String[] args) throws java.lang.Exception
              {
                  String className = "Student"; //Passed the Class Name in String Object.
          
                   //A Object of Student will made by Invoking its Default Constructor.
                  Object o = Class.forName(className).newInstance(); 
                  if(o instanceof Student) // Verify Your Instance that Is it Student Type or not?
                  System.out.println("Hurrey You Got The Instance of " + className);
              }
          }
          class Student{
              public Student(){
                  System.out.println("Constructor Invoked");
              }
          
          }
          

          输出:-

           Constructor Invoked
           Hurrey You Got The Instance of Student
          

          【讨论】:

            猜你喜欢
            • 2019-02-09
            • 2014-11-22
            • 2015-09-08
            • 1970-01-01
            • 2012-12-20
            • 1970-01-01
            • 2011-02-26
            • 2012-05-22
            相关资源
            最近更新 更多