#java #generics
#java #общие
Вопрос:
Я провел тест универсального типа.
class A {}
class B extends A {}
существует два метода:
private static void extendTest(List<? extends A> superList) {
System.out.println("extendTest over.");
}
private static void extendMapTest(HashMap<String, List<? extends A>> superMap) {
System.out.println("extendMapTest over.");
}
и я создаю list
и map
:
List<B> childList = new ArrayList<>();
childList.add(new B());
extendTest(childList); // TAG1: it is OK.
HashMap<String, List<B>> childMap = new HashMap<>();
childMap.put("hello", childList);
extendMapTest(childMap); // TAG2: ERROR!
почему TAG1 в порядке, а TAG2 — ошибка?
как я могу исправить TAG2?
Комментарии:
1. В чем ошибка?
Ответ №1:
List<? extends A>
не является супертипом List<B>
. См. Официальный учебник по обобщениям по верхней границе.
Чтобы исправить, определите дочерний список следующим образом:
List<A> childList = new ArrayList<>();
Вы все равно можете добавить a B
к a List<A>
, потому что a
B
— это an A
.
И определите свой метод map следующим образом:
private static void extendMapTest(HashMap<String, List<A>> superMap) {...
Ответ №2:
Следует учитывать одну вещь.
Вы можете создать другой класс
class C extends A {}
и внутри вашего extendMapTest(HashMap<String, List<? extends A>> superMap)
вы можете делать:
List<C> list = new ArrayList<>();
list.add(new C());
superMap.put("A", list);
но это противоречит объявлению объекта childMap, который вы передаете extendMapTest
HashMap<String, List<B>> childMap
Я предполагаю, что ошибка компиляции предотвращает эту или подобную ситуацию
Ответ №3:
это так же просто, как List<Integer>
не являются подтипом List<Number>
, даже если Number и Integer связаны и точно так AnyClass<A>
же не связаны с, AnyClass<B>
как показано в документах
Простой вариант — просто определить вашу карту с помощью подстановочного знака, изменение кода не требуется, например
HashMap<String, List<? extends A>> childMap = new HashMap<>();
например, с измененным кодом для демонстрации
class A {}
class B extends A {
public int a=9;
}
private static void extendTest(List<? extends A> superList) {
System.out.println("extendTest over.");
}
private static void extendMapTest(HashMap<String, List<? extends A>> superMap) {
System.out.println("extendMapTest over." ((B)(superMap.get("hello").get(0))).a);
}
List<B> childList = new ArrayList<>();
childList.add(new B());
extendTest(childList);
HashMap<String, List<? extends A>> childMap = new HashMap<>();
childMap.put("hello", childList);
extendMapTest(childMap);
Вывод:
extendTest over.
extendMapTest over.9