Важно понимать значение типа подстановочных знаков.
Вы уже поняли, что вы можете назначить Map<Integer, Map<Integer, String>>
к Map<?, ?>
, как Map<?, ?>
подразумевает произвольные типы, неизвестные, кто мог бы иметь ссылку заявленного типа Map<?, ?>
. Таким образом, вы можете присвоить любую карту до Map<?, ?>
.
Наоборот, если у вас есть Map<?, Map<?, ?>>
, то он имеет неизвестный тип ключа, но тип значения не неизвестен. Это Map<?,?>
тип, вспомните информацию выше, которую можно назначить с помощью любой.
Итак, следующий код является законным:
Map<?, Map<?, ?>> map=new HashMap<>();
map.put(null, Collections.<String,String>singletonMap("foo", "bar"));
map.put(null, Collections.<Double,Integer>singletonMap(42.0, 1000));
map.put(null, Collections.<Object,Boolean>singletonMap(false, true));
Здесь мы прикладываем null
ключа, как мы не можем put
что-нибудь еще для ключей, но произвольные набранным карт как значения, как это то, что тип значения Map<?, ?>
подразумевает: может быть задан с произвольных карт. Обратите внимание, что на iterating over the entries мы можем также set other entries с ключами null
на произвольные карты.
Так что я вполне уверен, что вы не хотите, чтобы назначить ваш Map<Integer, Map<Integer, String>>
к Map<?, Map<?, ?>>
и обнаружить произвольные карты, не будучи Map<Integer, String>
как значения впоследствии, и что вы вполне счастливы, что компилятор не позволяет этого.
То, что вы на самом деле хотите сделать это, чтобы назначить карту к типу, который имеет как, ключ и значение типа, неизвестно, но до сих пор, говоря, что ваши ценности карты:
Map<Integer, Map<Integer, String>> someMap = new HashMap<>();
Map<?, ? extends Map<?, ?>> map=someMap;
В системе Map<Integer, String>
общего типа является подтипом Map<?, ?>
, поэтому вы можете назначить его Map<?, ?>
, а также ? extends Map<?, ?>
. Это отношение подтипа не отличается от отношения String
к Object
. Вы можете присвоить любую String
переменной типа Object
, но если у вас есть Map<?,String>
, вы не можете назначить ее Map<?,Object>
, но только по Map<?, ? extends Object>
по той же причине: карта должна содержать String
s как значения, а не принимать произвольные объекты.
Обратите внимание, что вы можете обходить это ограничение.Вы можете сказать:
Map<Integer, Map<Integer, String>> someMap = new HashMap<>();
Map<?, Map<?, ?>> map=Collections.unmodifiableMap(someMap);
Поскольку карта возвращаемый unmodifiableMap
не допускает каких-либо изменений, что позволяет расширить ключ и значение типа. Содержащиеся значения имеют заданный тип (т. Е. Map<?, ?>
), когда вы запрашиваете карту, но попытки помещать произвольные значения карты, а не отклоняются компилятором, будут отклонены во время выполнения.
В чем вопрос? –
'return someMap; // компиляция не завершена' – Dmytro
Возможный дубликат [Несколько подстановочных знаков для общих методов делает Java-компилятор (и меня!) очень путать] (http://stackoverflow.com/questions/3546745/multiple-wildcards-on-a-generic- методы-make-java-compiler-and-me-very-confu) –