在运行时使用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);
当然,不是param1
和param2
你可以根据输入文件中的内容创建一个参数数组(对于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
在这种情况下只能使用字符串,因为它们是从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 */ );