Java:没有默认构造函数的类的新实例

我正在尝试为我的学生的家庭作业构建一个自动测试框架(基于jUnit,但这并不重要)。他们将不得不为一些类创建构造函数,并向它们添加一些方法。稍后,使用我提供的测试功能,他们将检查它们是否正常。

我想做的是,通过反思,创建一个我想要测试的类的新实例。问题是,有时没有默认构造函数。我不在乎这些,我想创建一个实例并自己初始化实例变量。有什么办法可以做到这一点吗?很抱歉,如果以前有人问过这个问题,但只是我找不到任何答案。

提前致谢。


答案 1

调用,然后传入适当的参数。示例代码: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);           
    }
}

答案 2

这是一个通用解决方案,不需要javassist或其他字节码“操纵器”。虽然,它假设构造函数除了简单地将参数分配给相应的字段之外没有做任何其他事情,因此它只是选择第一个构造函数并创建一个具有默认值的实例(即int为0,Object为n null等)。

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;
}

P.S. 适用于 Java 1.5+。该解决方案还假定没有可以阻止调用 的 SecurityManager 管理器。f.setAccessible(true)