假设我们有以下内容:
public class Parent{
public void setXXX(String XXX);
public String getXXX();
}
public class Children extends Parent{
....
}
现在我想创建一个名为clone List的方法,如下所示:
public List<Something> cloneList(List<Something> original){
List<Something> newList=new ArrayList<>();
for(Something e:original){
Something newE=new Something();
newE.setXXX(e.getXXX());
newList.add(newE);
}
return newList;
}
我们希望cloneList可以同时应用于List<Parent>
和List<Children>
,那么无论如何适用于“Something”?
由于Java Collection<Parent>
与Collection<Children>
假设: 1.不想使用任何序列化方法或反思。
我们无法修改Parent和Children类。这是在第三方Jar中预定义的。
SuperParent类是不可能的,因为我们无法按照2中的说明修改Parent。
答案 0 :(得分:2)
这在Java中是不可能的。看看Generic syntax for extends or equal to。
您可以按如下方式更改方法,并使您的Parent类扩展SuperParent。
public static <T extends SuperParent> List<T> cloneList(List<T> original, Class<T> type) throws IllegalAccessException, InstantiationException {
List<T> newList=new ArrayList<>();
for(T e : original){
T x = type.newInstance();
x.setXXX(e.getXXX());
newList.add(x);
}
return newList;
}
此外,您可以选择其他克隆方法。例如,使用Apache Commons'SerializationUtils
:
List<Children> result = (List<Children>) SerializationUtils.clone(originalList);
答案 1 :(得分:1)
你不能以这种方式使用泛型,只能反射。
对于类型变量T
,您无法使用new T()
。这是因为泛型是一种编译时机制,并且在运行时使用new
来创建特定类型的对象,并且编译器无法在编译时创建对该类型的适当引用。所以虽然:
new ArrayList<T>();
是合法的,因为编译器实际上将其编译为用于创建原始ArrayList
类型的代码,这个:
new T();
不是,因为编译器甚至不知道实际的类是什么(即使它只被定义为T extends Parents
它可能是一个在编译程序时甚至没有编写的类,如{ {1}}或其他东西),甚至不知道它是否有无参数构造函数。
答案 2 :(得分:0)
将cloneList
的签名更改为:
public <X extends Parent> List<X> cloneList(final List<X> original)
然后它将起作用,至少对于方法签名。您可以在内部构建List<Parent>
然后将其强制转换为List<X>
,并在需要时忽略警告;没有办法找出&#34; X&#34;。
答案 3 :(得分:0)
从一般意义上讲,您应该能够使用具有此签名的方法:
public <T extends Parent> List<T> cloneList(List<T> original)
然而,这不是你最大的问题。这将获得列表元素的副本。您的代码无法使用
T newE = new T(); // doesn't work
因为无法保证存在类型参数T的无效构造函数。相反,您需要一种方法来返回正确类型的副本。完全类型安全,你不能这样做,但你可以接近。您可以实现以下方法:
public Parent Parent.copy();
public Children Children.copy();
......以任何合适的方式,然后像这样编写你的方法:
public <T extends Parent> List<T> cloneList(List<T> original) {
List<T> newList = new ArrayList<>();
for (T originalItem : original) {
newList.add(original.getClass().cast(original.copy()));
}
return newList;
}
(请注意,虽然记录的Object.getClass()
返回类型为Class<?>
,但不能用于此目的,但method documentation表示返回类型实际上比这足以使这项工作。)