如何在 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... 结构的对象。
我有这个代码:
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... 结构的对象。