Универсальные Типы («Список » ) в значении HashMap

#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