在运行时使用reflection来实例化未知类的对象的正确方法是什么?

我正在使用Configuration Loader类,以便我可以通过外部文本文件(config.txt)更改程序的参数,而不必每次更改时都重新编译我的代码。

有人建议我使用Java的Reflection来做到这一点,但我对如何实现它有点困惑。

我已经能够从我的文本文件成功提取其构造函数的类名和参数,但是如何从这个实例化对象?

到目前为止,这是我的方法:

public void loadObject(String classString, HashMap hm) { String className = props.getProperty(classString); Class c = Class.forName(className); } 

classString是一个包含类名的字符串,hm是一个hashmap,其中类的构造函数参数映射到它们的预期值。

即,对于class Foo (int xPos, float yPos) ,“xPos”将映射到预期int的字符串,“yPos”映射到预期float的字符串。 我希望能够返回new Foo(hm.get"xPos".toInt, hm.get"yPost".toFloat) ,但我不确定如何动态使用这样的构造函数(问题是,有多个可能的类 – 例如,它可能是一个bar而不是一个foo

我知道可以基于classString做一个基于if / else的操作,并且在识别它之后简单地调用正确的构造函数,但是我希望创建一个更加可扩展的代码,每次添加时都不需要重写该课程的新课程。

所有可能的对象都从单个父对象inheritance。

您将使用Class.getConstructor(Class... parameterTypes)来获取对构造函数的引用,后跟Constructor.newInstance(Object... initargs)

但是我建议看一下dependency injection框架,比如Spring或Guice,因为它听起来像你正在创建的是他们所做的基本版本。

根据要求扩大此答案:

 Class c = Class.forName(name); Constructor ctor = c.getConstructor(Integer.class, Integer.class); Integer param1 = hm.get("xPos") ...; Integer param2 = hm.get("yPos") ...; Object instanceOfTheClass = ctor.newInstance(param1, param2); 

当然,不是param1param2你可以根据输入文件中的内容创建一个参数数组(对于getConstructor()的参数getConstructor() )等。

这是从程序参数中执行此操作的示例:

 import java.lang.reflect.Constructor; import java.util.*; public class InstantiateWithReflectionIncludingArgs { public static void main(String[] args) throws Exception { String className = args[0]; List argList = new ArrayList(); if (args.length > 1) { argList.addAll(Arrays.asList(args).subList(1, args.length)); } Class c = Class.forName(className); List> argTypes = new ArrayList>(); for (Object arg : argList) { argTypes.add(arg.getClass()); } Constructor constructor = c.getConstructor( argTypes.toArray(new Class[argTypes.size()])); Object o = constructor.newInstance( argList.toArray(new Object[argList.size()])); System.out.println("Created a " + o.getClass() + ": " + o); } } 

当然, argList在这种情况下只能使用字符串,因为它们是从String[]提取的,但是你可以添加任何类型的args。 请注意,构造函数args是位置的,而不是命名的,因此地图中的名称对您没有多大帮助。 他们需要处于正确的顺序。

尝试运行它并传递“java.util.Date”作为参数。

 Class clazz = MyClass.class; Constructor ctor = clazz.getConstructor( /* Array of Classes the constructor takes */); ctor.newInstance( /* arguments the constructor takes */ );