Java:不能通用List <! - ?扩展Parent - > mylist

时间:2011-04-23 11:40:55

标签: java list generics inheritance collections

另一个例子非常复杂,我根本不理解它,我的问题在某种程度上是类似的,但正如我所说的那样更简单,可能会在更简单的答案中产生

public List<? extends Parent> myfunction(List<? extends Parent> mylist){
       mylist.add(new Child())  ; //Doesn't Compile
}

4 个答案:

答案 0 :(得分:8)

我相信你正在寻找一个获取列表,添加内容然后返回列表的方法。该列表是通用的,您希望返回类型与参数的类型匹配。

在一般情况下,您就是这样做的:

public <T extends Parent> List<T> myfunction(List<T> myList) {
   ... // Add something to myList
   return myList;
} 

具体而言,您正尝试将new Child()添加到myList。这不行。可以使用多种列表调用myfunction(),而添加new Child()只有在列表为List<Parent>List<Child>时才有效。以下是不同类型List的示例:

public static class Parent {}  
public static class Child extends Parent {}  
public static class OtherChild extends Parent {}

public <T extends Parent> List<T> myfunction(List<T> myList) {
  myList.add(new Child());
  return myList;
} 

myfunction(new ArrayList<OtherChild>());

在最后一行中,使用myfunction()对象列表调用OtherChild。显然,在这样的列表中添加Child对象是非法的。编译器通过拒绝myfunction()

的定义来防止这种情况

<强>附录

如果您希望myfunction()能够向myList添加元素,则需要使用工厂(因为Java不允许new T()其中T是类型参数 - 由于type erasure)。以下是myfunction()应该是这样的:

public interface Factory<T> {
  public T create();
}

public <T extends Parent> List<T> myfunction(List<T> myList, 
                                             Factory<? extends T> factory) {
  myList.add(factory.create());
  return myList;
} 

现在,它的用法:

public static class ChildOfOtherChild extends OtherChild {}

myfunction(new ArrayList<OtherChild>(), new Factory<ChildOfOtherChild>() {
    @Override public ChildOfOtherChild create() { return new ChildOfOtherChild(); }
  });
}

答案 1 :(得分:5)

List<? extends Parent>的含义是“只包含某些未知子类Parent的实例的列表” - 由于您不知道它是哪个子类,因此除了{之外不能添加任何内容{1}}到列表中(你可以从中获取null个实例)。

如果您要将特定的子类Parent添加到列表中,那么您真正需要的是:

Child

答案 2 :(得分:1)

关注Jon Skeet在other question中的示例,假设您使用了

public List<? extends Fruit> myfunction(List<? extends Fruit> mylist){
       mylist.add(new Apple())  ; //Doesn't Compile
       return myList;
}

然后用

调用它
List<Banana> bananas = new ArrayList<Banana>();
bananas = myfunction(bananas);

您无法将苹果添加到香蕉列表中。

可以做的是

public List<Fruit> addApple(List<Fruit> mylist){
       mylist.add(new Apple())  ; 
       return myList;
}

public List<Fruit> addBanana(List<Fruit> mylist){
       mylist.add(new Banana())  ; 
       return myList;
}

答案 3 :(得分:-2)

如何添加return语句,或声明方法返回void ...