Ответ 1
Он спроектирован таким образом, поскольку во время операции get для определения возвращаемого объекта используются только equals
и hashCode
. Реализация метода get
не проверяет тип объекта, используемого в качестве ключа.
В вашем примере вы пытаетесь получить значение, передавая long как myHashMap.get(1L);
во-первых, хеш-код объекта Long
со значением 1L
будет использоваться для определения сегмента, из которого нужно искать. Затем метод equals
ключа используется, чтобы узнать точную запись карты, из которой нужно вернуть значение. И в четко определенном методе equals
всегда есть проверка для типа:
public boolean equals(Object obj) {
if (obj instanceof Long) { //here type is checked
return value == ((Long)obj).longValue();
}
return false;
}
Таким образом, если типы не равны, метод equals
возвращает false
и, следовательно, get
также возвращает null
.
В некоторых случаях, например при использовании List
в качестве ключа, может случиться так, что вы поместите элемент на карту, используя экземпляр, скажем, ArrayList
но вы можете успешно извлечь то же значение с помощью экземпляра LinkedList
. Так как оба реализуют интерфейс List
.
Map<List<String>, String> myHashMap = new HashMap<>();
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
myHashMap.put(arrayList, "foo");
System.out.println(myHashMap.get(linkedList));
Приведенный выше код будет выводиться в консоли foo
.
Здесь, хотя реализации отличаются, но если вы исследуете метод equals
ArrayList
, он только проверяет, является ли тип List
:
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) { //checking type of super interface
return false;
}
...
}
То же самое относится и к LinkedList
.