简体   繁体   中英

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

The other Example is pretty complex and I didn't understand it at all, my problem is similar somehow but as I said it's simpler and might yield in simpler answer

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

I believe you're looking for a method that takes a list, adds something to it, and then returns the list. The list is generic and you want the return type to match the type of the parameter.

Here's how you do it, in the general case:

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

Specifically, you're trying to add new Child() to myList . This cannot work. myfunction() may be called with many kinds of lists, whereas adding new Child() can only work if the list is either a List<Parent> or a List<Child> . Here's an example for a List of different kind:

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>());

In the last line, myfunction() is called with a List of OtherChild objects. Obviously, adding a Child object into such a list is illegal. The compiler prevents that by rejecting the definition of myfunction()

Appendix

If you want myfunction() to be able to add an element to myList you need to use a factory (since Java does not allow new T() where T is a type parameter - due to type erasure ). Here's how myfunction() should look like:

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;
} 

And now, its usage:

public static class ChildOfOtherChild extends OtherChild {}

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

What List<? extends Parent> List<? extends Parent> means is "a list that contains only instances of some unknown subclass of Parent " - and since you don't know what subclass it is, you can't add anything except null to the list (you can get Parent instances from it, though).

If you have a specific subclass Child that you want to add instances of to the list, then what you really need is this:

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

Following on Jon Skeet's example in the other question , let's say you used

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

but then called it with

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

You can't add an apple to a list of bananas.

What you can do is

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 ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM