Java: не может в общий списокмой список - PullRequest
1 голос
/ 23 апреля 2011

Другой пример довольно сложный, и я его совсем не понял, моя проблема как-то похожа, но, как я уже сказал, он проще и может дать более простой ответ

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

Ответы [ 4 ]

8 голосов
/ 23 апреля 2011

Я полагаю, вы ищете метод, который берет список, добавляет что-то к нему, а затем возвращает список.Список является общим, и вы хотите, чтобы тип возвращаемого значения соответствовал типу параметра.

Вот как вы это делаете, в общем случае:

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>.Вот пример для списка другого типа:

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 - параметр типа - из-за стирание типа ).Вот как должен выглядеть 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(); }
  });
}
5 голосов
/ 23 апреля 2011

Что означает List<? extends Parent>, это «список, который содержит только экземпляры некоторого неизвестного подкласса Parent» - и, поскольку вы не знаете, что это за подкласс, вы не можете ничего добавить, кроме null, кlist (однако вы можете получить Parent экземпляров из него).

Если у вас есть определенный подкласс Child, для которого вы хотите добавить экземпляры в список, то вам действительно нужно следующее:

public List<Child> myfunction(List<Child> mylist)
1 голос
/ 23 апреля 2011

Следуя примеру Джона Скита в другом вопросе , допустим, вы использовали

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;
}
0 голосов
/ 23 апреля 2011

Как насчет добавления оператора return или объявления метода, возвращающего void ...

...