Наследование Java с параметризованными списками - PullRequest
2 голосов
/ 10 апреля 2011

У меня странная проблема с наследованием, и я не понимаю, почему оно не должно работать:

public interface A {  }

public interface B extends A {}


public class C {
void test() {
    ArrayList<A> foo = new ArrayList<B>();
    }
}

Но компиляция дает мне следующую ошибку

Type mismatch: cannot convert from ArrayList<B> to ArrayList<A> C.java /bla/src/de/plai/test line 8 Java Problem

Ответы [ 3 ]

7 голосов
/ 10 апреля 2011

Поначалу это может показаться нелогичным, но даже если класс B является подклассом A, List<B> не является подклассом List<A>. Я дал более подробное объяснение и пример в этом предыдущем ответе на аналогичный пост. См. Также этот другой ответ для ссылки на соответствующий элемент в Effective Java 2nd Edition .

Решением этой проблемы является использование групповых символов . Таким образом, вы должны объявить свой список как

List<? extends A> foo = new ArrayList<B>();
4 голосов
/ 10 апреля 2011
ArrayList<? extends A> foo = new ArrayList<B>();

Список A - это не то же самое, что Список B, потому что вы не можете гарантировать согласованность содержимого в списке.

А именно, если бы это было возможно, вы могли бы вставить элемент типа A в список, экземпляр которого был создан только для содержания элементов B.

Конечно, приведенная выше декларация не позволит вам записать какие-либо элементы в список.Это объявление только для чтения.

Также хорошим принципом ООП является объявление переменных как интерфейсов, а не реализаций:

List<? extends A> foo = new ArrayList<B>();
1 голос
/ 10 апреля 2011

Было чуть выше, чтобы опубликовать то же самое :) ну, тем не менее .. ответ такой же, это должно работать для вас.

ArrayList<? extends A> foo = new ArrayList<B>();
...