Java List <parent>和List <children>方法</children> </parent>

时间:2014-10-30 15:02:19

标签: java list

假设我们有以下内容:

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.不想使用任何序列化方法或反思。

  1. 我们无法修改Parent和Children类。这是在第三方Jar中预定义的。

  2. SuperParent类是不可能的,因为我们无法按照2中的说明修改Parent。

4 个答案:

答案 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表示返回类型实际上比这足以使这项工作。)