【问题标题】:Dynamically loading a class in Java在 Java 中动态加载一个类
【发布时间】:2011-07-31 02:21:24
【问题描述】:

我查找了语法并搜索了 api,但仍然对过程感到困惑。我还搜索了 Stackoverflow。加载类并动态创建对象的正确方法是什么?换句话说,我希望用户指定他们想要创建的对象类型,然后创建该类型的对象。我不想要菜单,因为我希望他们能够选择当前目录中的任何类。

【问题讨论】:

  • 您是在尝试从 binary.class 文件还是通过类名加载类?
  • @JustinWaugh 嗨贾斯汀,接受的答案是否适合加载 .class 文件?

标签: java dynamic


【解决方案1】:

假设类有无参数构造函数,最简单的方法是 -

Object newObject = Class.forName(strFullyQualifiedClassName).newInstance();

参考 - java.lang.Class

【讨论】:

  • 如果它有 arg 怎么办,以及如何调用类上的方法 -- 如何仅通过类名强制转换 newObject?当我尝试在 Object 类型上调用类的方法时,它告诉我该方法未定义对象。
  • 如果您在编译时不知道类的类型,您将不得不使用反射来查找和调用方法。如果构造函数有一个参数,您可以在从 Class.forName 返回的类上使用 getDeclaredConstructor(),如 Mike Samuel 的回答所示
  • +1 给贾斯汀。另外,实际上,你不可能对这个类一无所知,因为那样实际使用它会非常困难。让这些未知类实现特定接口通常是一个好策略。然后,您可以通过接口引用这些对象,以便您可以在它们上调用方法等。
  • 一个类的全限定类名是什么?
  • 你不应该使用.newInstance()。如果零参数构造函数抛出已检查的异常,.newInstance() 会将它们作为运行时异常清洗,因此您将失去异常安全性。来自 javadoc:“使用此方法可以有效地绕过编译器执行的编译时异常检查。”
【解决方案2】:

ClassLoader.loadClass 将加载一个类。你通过myClass.getClassLoader() 获得了一个类加载器,如果它为空,你应该回退到ClassLoader.getSystemClassLoader()

一旦你有了一个类实例,你就可以通过getDeclaredConstructor(...) 得到它的构造函数。 因此,如果您有一个 public class MyClasspublic MyClass(String) { ... } 这样的构造函数,那么

Class<MyClass> clazz = MyClass.class;
Constructor<MyClass> ctor = clazz.getDeclaredConstructor(String.class);
MyClass instance = ctor.newInstance("foo");

上面忽略了一堆可能的异常。

【讨论】:

  • MyClass 是类的实例还是静态引用?有什么方法可以通过将类的名称作为字符串传递给方法来获取类的构造函数?或者有什么类似的方式?
  • MyClass 是本例中类的名称。一个类可以有多个构造函数(或者没有接口);类没有“构造函数”。
  • MyClass.class 的语法可能令人困惑。这只是引用MyClass 的类实例的一种方式。所以String.class.isInstance(x)x instanceof String 的另一种说法。
  • 如何在不实际硬编码类名的情况下创建实例?我想通过将字符串传递给函数来加载类,它会构造并实例化该类的对象。
  • @rubixibuc, Class&lt;?&gt; clazz = myClassLoader.loadClass(className) 如第一段所述。
【解决方案3】:

这是我的工作。这不是一个完成的产品,而只是测试我是否可以让它工作。感谢所有回答问题的人:-)。

public class SimLoader {  
  public static void main(String[] args)  
  {  
    try  
    {  
    Object simulator = Class.forName("SimX").newInstance();  
    ((SimInterface)simulator).run();  
    }  
    catch(ClassNotFoundException e) {}  
    catch(InstantiationException e) {}  
    catch(IllegalAccessException e) {}  
    }  
  }  
interface SimInterface {  
 void run();  
}  
class SimX implements SimInterface  
{  
  public void run() {  
    System.out.println("Success");  
  }  
}  

【讨论】:

  • 对我来说最好的解决方案。但不要忘记对 Class 使用 FullyQualifiedName(如 com.mycomapy.SimX,在您的示例中可能不需要)。
猜你喜欢
  • 2012-07-20
  • 2016-03-12
  • 1970-01-01
  • 2011-04-04
  • 2012-10-10
  • 2010-12-14
  • 1970-01-01
  • 2014-11-16
  • 1970-01-01
相关资源
最近更新 更多