我可以在使用构造函数参数时使用Class.newInstance()吗?

269

我想使用 Class.newInstance(),但是我要实例化的类没有无参构造函数。因此,我需要能够传入构造函数参数。是否有一种方法可以做到这一点?


2
一个很好的答案可以考虑 Chris Jester-Young 的回答。 - developer_hatch
9个回答

235
MyClass.class.getDeclaredConstructor(String.class).newInstance("HERESMYARG");
或者
obj.getClass().getDeclaredConstructor(String.class).newInstance("HERESMYARG");

27
澄清一下,getDeclaredConstructor 不是静态方法,你需要在特定类的实例上调用它。 - clum
1
似乎对于Java 1.1来说,答案是否定的。 - Jim
我有一个带有List<String>参数的公共构造函数。使用getDeclaredConstructor无法获取它,但是使用getConstructor可以正常工作。您知道为什么吗? - Line
需要注意的是,这需要你捕获一系列的异常。当我意识到至少有4个异常时,我只是将其放在了try/catch块中。此外,getDeclaredConstructor()的参数是构造函数参数的类。 - Andrew Puglionesi

91
myObject.getClass().getDeclaredConstructors(types list).newInstance(args list);

编辑:根据评论,似乎仅指出类和方法名称对于某些用户不够。要获取更多信息,请查看获取构造函数调用它的文档。


20
答案没有说明如何传递参数或给出示例,只是一个猜测。 - djangofan
3
应该是使用 getDeclaredConstructor(单数形式)吗? - Luke Skywalker
2
@ryvantage并没有让它看起来像一个静态方法,因为所有的调用都在“myObject”实例上进行。这只是一系列方法调用的链条。而且我不确定为什么55个人觉得这个答案有用,因为它是错误的,正确的答案在下面! - sbnarra

85
假设您有以下构造函数:
class MyClass {
    public MyClass(Long l, String s, int i) {

    }
}

您需要展示您打算像这样使用该构造函数:

Class classToLoad = MyClass.class;

Class[] cArg = new Class[3]; //Our constructor has 3 arguments
cArg[0] = Long.class; //First argument is of *object* type Long
cArg[1] = String.class; //Second argument is of *object* type String
cArg[2] = int.class; //Third argument is of *primitive* type int

Long l = new Long(88);
String s = "text";
int i = 5;

classToLoad.getDeclaredConstructor(cArg).newInstance(l, s, i);

20

9

8

按照以下步骤调用带参数的构造函数:

  1. 通过在 Class[] 中传递类型来获取具有参数类型的构造函数,使用 ClassgetDeclaredConstructor 方法
  2. 通过在 Object[] 中传递值来创建构造函数实例,使用 ConstructornewInstance 方法

示例代码:

import java.lang.reflect.*;

class NewInstanceWithReflection{
    public NewInstanceWithReflection(){
        System.out.println("Default constructor");
    }
    public NewInstanceWithReflection( String a){
        System.out.println("Constructor :String => "+a);
    }
    public static void main(String args[]) throws Exception {

        NewInstanceWithReflection object = (NewInstanceWithReflection)Class.forName("NewInstanceWithReflection").newInstance();
        Constructor constructor = NewInstanceWithReflection.class.getDeclaredConstructor( new Class[] {String.class});
        NewInstanceWithReflection object1 = (NewInstanceWithReflection)constructor.newInstance(new Object[]{"StackOverFlow"});

    }
}

输出:

java NewInstanceWithReflection
Default constructor
Constructor :String => StackOverFlow

1
您可以使用Class的getDeclaredConstructor方法。它需要一个类数组。这里有一个经过测试和工作的示例:

getDeclaredConstructor 方法。它期望一个类数组。这是一个经过测试和工作的示例:

public static JFrame createJFrame(Class c, String name, Component parentComponent)
{
    try
    {
        JFrame frame = (JFrame)c.getDeclaredConstructor(new Class[] {String.class}).newInstance("name");
        if (parentComponent != null)
        {
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
        else
        {
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        }
        frame.setLocationRelativeTo(parentComponent);
        frame.pack();
        frame.setVisible(true);
    }
    catch (InstantiationException instantiationException)
    {
        ExceptionHandler.handleException(instantiationException, parentComponent, Language.messages.get(Language.InstantiationExceptionKey), c.getName());
    }
    catch(NoSuchMethodException noSuchMethodException)
    {
        //ExceptionHandler.handleException(noSuchMethodException, parentComponent, Language.NoSuchMethodExceptionKey, "NamedConstructor");
        ExceptionHandler.handleException(noSuchMethodException, parentComponent, Language.messages.get(Language.NoSuchMethodExceptionKey), "(Constructor or a JFrame method)");
    }
    catch (IllegalAccessException illegalAccessException)
    {
        ExceptionHandler.handleException(illegalAccessException, parentComponent, Language.messages.get(Language.IllegalAccessExceptionKey));
    }
    catch (InvocationTargetException invocationTargetException)
    {
        ExceptionHandler.handleException(invocationTargetException, parentComponent, Language.messages.get(Language.InvocationTargetExceptionKey));
    }
    finally
    {
        return null;
    }
}

1

0

这是我如何使用动态构造函数参数列表创建 Class clazz 实例的方法。

final Constructor constructor = clazz.getConstructors()[0];
final int constructorArgsCount = constructor.getParameterCount();
if (constructorArgsCount > 0) {
    final Object[] constructorArgs = new Object[constructorArgsCount];
    int i = 0;
    for (Class parameterClass : constructor.getParameterTypes()) {
        Object dummyParameterValue = getDummyValue(Class.forName(parameterClass.getTypeName()), null);
        constructorArgs[i++] = dummyParameterValue;
    }
    instance = constructor.newInstance(constructorArgs);
} else {
    instance = clazz.newInstance();
}

这是 getDummyValue() 方法的代码实现:

private static Object getDummyValue(final Class clazz, final Field field) throws Exception {
    if (int.class.equals(clazz) || Integer.class.equals(clazz)) {
        return DUMMY_INT;
    } else if (String.class.equals(clazz)) {
        return DUMMY_STRING;
    } else if (boolean.class.equals(clazz) || Boolean.class.equals(clazz)) {
        return DUMMY_BOOL;
    } else if (List.class.equals(clazz)) {
        Class fieldClassGeneric = Class.forName(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0].getTypeName());
        return List.of(getDummyValue(fieldClassGeneric, null));
    } else if (USER_DEFINED_CLASSES.contains(clazz.getSimpleName())) {
        return createClassInstance(clazz);
    } else {
         throw new Exception("Dummy value for class type not defined - " + clazz.getName();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接