Ger*_*anK 39 java reflection constructor instance new-operator
我正在尝试为学生的作业构建一个自动测试框架(基于jUnit,但这并不重要).他们必须为某些类创建构造函数,并为它们添加一些方法.后来,通过我提供的测试功能,他们将检查它们是否正常.
我想做的是,通过反射,创建一个我想要测试的类的新实例.问题是,有时候,没有默认的构造函数.我不关心这个,我想创建一个实例并自己初始化实例变量.有没有办法做到这一点?我很抱歉,如果之前有人问过,但我找不到任何答案.
提前致谢.
Jon*_*eet 51
调用Class.getConstructor()然后Constructor.newInstance()传入适当的参数.示例代码:
import java.lang.reflect.*;
public class Test {
public Test(int x) {
System.out.println("Constuctor called! x = " + x);
}
// Don't just declare "throws Exception" in real code!
public static void main(String[] args) throws Exception {
Class<Test> clazz = Test.class;
Constructor<Test> ctor = clazz.getConstructor(int.class);
Test instance = ctor.newInstance(5);
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个通用的解决方案,不需要javassist或其他字节码"操纵器".虽然,它假设构造函数除了简单地将参数分配给相应的字段之外没有做任何其他事情,因此它只选择第一个构造函数并创建一个具有默认值的实例(即0表示int,null表示Object等).
private <T> T instantiate(Class<T> cls, Map<String, ? extends Object> args) throws Exception
{
// Create instance of the given class
final Constructor<T> constr = (Constructor<T>) cls.getConstructors()[0];
final List<Object> params = new ArrayList<Object>();
for (Class<?> pType : constr.getParameterTypes())
{
params.add((pType.isPrimitive()) ? ClassUtils.primitiveToWrapper(pType).newInstance() : null);
}
final T instance = constr.newInstance(params.toArray());
// Set separate fields
for (Map.Entry<String, ? extends Object> arg : args.entrySet()) {
Field f = cls.getDeclaredField(arg.getKey());
f.setAccessible(true);
f.set(instance, arg.getValue());
}
return instance;
}
Run Code Online (Sandbox Code Playgroud)
PS适用于Java 1.5+.该解决方案还假设没有可能阻止调用的SecurityManager管理器f.setAccessible(true).