Java:不能通用List<?

Java: Can't to generic List<? extends Parent> mylist

另一个例子相当复杂,我根本不理解,我的问题在某种程度上是相似的,但正如我所说,它更简单,可能会得到更简单的答案。

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


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

一般情况下,您可以这样做:

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

具体来说,您试图将new Child()添加到myList中。这行不通。myfunction()可以用多种列表来调用,而添加new Child()只能在列表为ListList的情况下使用。下面是一个不同类型列表的示例:

1
2
3
4
5
6
7
8
9
10
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>());

在最后一行中,使用OtherChild对象列表调用myfunction()。显然,将Child对象添加到这样的列表中是非法的。编译器通过拒绝myfunction()的定义来防止这种情况的发生。

附录

如果您希望EDCOX1×9可以将一个元素添加到EDCOX1(8),则需要使用一个工厂(因为Java不允许EDCOX1×19)其中T是类型参数-由于类型擦除)。下面是myfunction()应该是什么样子:

1
2
3
4
5
6
7
8
9
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;
}

现在,它的用法是:

1
2
3
4
5
6
public static class ChildOfOtherChild extends OtherChild {}

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


List的意思是"一个只包含Parent某些未知子类实例的列表",由于您不知道它是什么子类,所以不能在列表中添加除null以外的任何内容(不过,您可以从中获取Parent实例)。

如果您有一个特定的子类Child,想要将的实例添加到列表中,那么您真正需要的是:

1
public List<Child> myfunction(List<Child> mylist)


下面是乔恩·斯基特在另一个问题中的例子,假设您使用

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

但后来用

1
2
List<Banana> bananas = new ArrayList<Banana>();
bananas = myfunction(bananas);

你不能在香蕉清单上加一个苹果。

你能做的就是

1
2
3
4
5
6
7
8
9
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;
}

添加一个return语句,或者声明返回void的方法,怎么样?