如何在 java 泛型方法中初始化一个实例

how to init an instance in a java generic method

我有这个代码:

    public <V> V getPropertiesByObject(V sample) throws TimeoutException {
//settings fields using reflaction
        return sample;
    }

我这样称呼它:

MyClass a = getPropertiesByObject(new MyClass());

只是因为我不知道如何构造实例。

我更愿意:

public <V> V getPropertiesByObject(Class<V> sample) throws TimeoutException {
//how to create a new V instance?
    return result;
}

有没有办法重构我的原始代码?

如果V有一个无参数的构造函数,你可以使用Class<V>::newInstance()

public <V> V getPropertiesByObject(Class<V> sample) throws TimeoutException {
    V result = sample.newInstance();
    // stuff on V
    return result;
}

当然,你会这样使用它:MyClass a = getPropertiesByObject(MyClass.class)

如果你必须指定一些参数,你可以这样做:

public <V> V getPropertiesByObject(Class<V> sample, Object... params) throws TimeoutException {
    V result = sample.newInstance();
    result.param0 = params[0];
    result.param1 = params[1];
    // etc  
    return result;
}

但在这两种情况下,MyClass 必须 具有无参数构造函数。如果你不能编辑 MyClass,你应该使用 Constructor.

的波希米亚人的答案

您可以使用反射 - 这是显示一种方法的基本实现:

public <V> V getPropertiesByObject(Class<V> clazz, Object... params) throws TimeoutException {
    Class<?>[] paramClasses = new Class<?>[params.length];
    for (int i =0; i < params.length; i++)
        paramClasses[i] = params[i].getClass(); 
    V result = clazz.getConstructor(paramClasses).newInstance((Object[])params);
    return result;
}

参数params,可以为空,是传递给那些参数对应的构造函数的参数。此代码不会处理 null 值。您可以这样称呼它:

String str = getPropertiesByObject(String.class); // blank String
Integer i = getPropertiesByObject(Integer.class, "1"); // 1

所以您想创建一个方法来创建任何可能的实例 class 并将任何可能的字段设置到该实例?

这很难。像 GSON 这样的框架有同样的问题,它们要么要求你在使用的 bean 中有一个无参数的构造函数,要么提供一种方法来为某个class(参见Is default no-args constructor mandatory for Gson?)创建实例。

Else 对于您的特定情况 - 如果您知道要实例化的 classes 的集合,那么您可以实现一个工厂 class,它基于 class 创建实例] 具有某种 if-else-if-else... 结构的对象。