Создание объекта коллекции с использованием Generics
Когда я пытаюсь создать объект, как показано ниже:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
Что не так синтаксически, может ли кто-нибудь объяснить мне?
Ответы
Ответ 1
Дженерики не являются ко-вариантами. Вы можете использовать:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
^ ^
--------------^------------------- becomes ------^ |
-----------------must remain as type ---------------
В то время как Map
на внешней левой стороне присваивания может "стать" a HashMap
назначенным, то же самое нельзя применить к любым типам, которые отображаются как общие параметры.
Edit:
Как отмечено @Keppil, вы можете использовать ограниченный синтаксис подстановки:
Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
Обратите внимание, что этот синтаксис не позволяет добавлять записи к карте, но полезен в качестве типа, который должен быть передан и из методов.
Некоторые ссылки:
Ответ 2
Аналогичная ошибка, например
List<Animal> list = new ArrayList<Dog>();
Параметрированный тип должен быть одного типа с обоих концов. Концепции наследования (IS-A) нет. Если вы все еще хотите использовать его, используйте подстановочный знак (?) С ключевым словом extend/super, который разрешен только по левой стороне знака равенства.
List<Animal> list = new ArrayList<Dog>(); // is not allowed
но
Animal[] animal = new Dog[10]; //is allowed
animal[0] = new Dog(); // is allowed
где он позже выйдет из строя и выдаст исключение, если кто-то попытается добавить объект Cat
(extends Animal).
animal[1] = new Cat(); //compiles fine but throws java.lang.ArrayStoreException at Runtime.
Помните animal[1]
или animal[index]
держит reference
для собаки. Таким образом, ссылочная переменная Dog
может ссылаться на объект Dog
object not Cat
.
Итак, чтобы избежать такого сценария, JSL внесла такие изменения в список обобщений /Collection. Этот ответ также применим для вашего вопроса (Map
).
Параметрированный тип должен быть одного типа с обоих концов.
List<Animal> list = new ArrayList<Animal>();
Ответ 3
Попробуйте это
Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
Проще объяснить на более простом примере
Set<Number> set = new HashSet<Integer>();
не разрешено, потому что тогда вы можете добавить Double to HashSet of Integer
set.add(1.0)
Обратите внимание, что
Set<? extends Number> set = new HashSet<Integer>();
не позволяет добавить ничего, кроме null
к набору. Но вы можете читать только цифры из него
Дополнительную информацию вы можете найти здесь http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
Ответ 4
вам нужно что-то вроде этого:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
myMap.put(1, new HashMap<String, Integer>());
Ответ 5
Map<String, Integer>
не совпадает с HashMap<String, Integer>
. Это проблема.
На самом деле HashMap реализует интерфейс карты. Поэтому он должен быть ? extends Map<String, Integer>
с левой стороны
Ответ 6
Попробуйте следующее:
Map<Integer, HashMap<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();