2011-10-08 30 views
8

我正在使用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”映射到预期的浮点的字符串。我想想要能够返回,new Foo(hm.get"xPos".toInt, hm.get"yPost".toFloat),但我不确定如何动态地使用这样的构造函数(问题是,有多个可能的类 - 例如它可能是bar而不是foo)。

我知道它有可能在基于classString的基础上执行if/else,并且在以这种方式识别它之后简单地调用正确的构造函数,但是我期待创建一个不必重写的更可扩展的代码每次我为程序添加一个新类。

所有可能的对象都从一个父对象继承。

回答

14

您将使用Class.getConstructor(Class<?>... parameterTypes)来获得对构造函数的引用,然后是Constructor.newInstance(Object... initargs)

但是,我会建议看一看依赖注入框架,如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())等

+0

恐怕我不明白你的伪代码的第一行。我根本不熟悉Reflection,所以我不确定你的代码实际上在做什么*。有可能扩大你的答案一点吗? –

+0

哦,好的,那么,按照上面的示例,Foo.GetConstructor会返回一个(int,float)数组?然后从那里我可以正确地将对象投射到Constructor.newInstance的initargs中? –

+1

+1使用现有解决方案进行Bean管理 –

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

下面是程序的参数做的一个例子:

import java.lang.reflect.Constructor; 
import java.util.*; 

public class InstantiateWithReflectionIncludingArgs { 
    public static void main(String[] args) throws Exception { 
     String className = args[0]; 
     List<Object> argList = new ArrayList<Object>(); 
     if (args.length > 1) { 
      argList.addAll(Arrays.asList(args).subList(1, args.length)); 
     } 
     Class c = Class.forName(className); 
     List<Class<?>> argTypes = new ArrayList<Class<?>>(); 
     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[]中提取的,但是您可以添加任何类型的参数。请注意,构造函数的参数是位置的,没有命名,所以地图上的名字不会对你有很大帮助。他们需要按照正确的顺序。

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

相关问题