Недавно от товарища пришел вопрос на засыпку: “Почему в интерфейсe java.util.Map метод get в качестве ключа принимает Object, а метод put использует женерики?”
V get(Object key);
V put(K key, V value);
Сходу ответить не смог, пришлось разбираться.
Сразу пришло на ум несколько гипотез:
- раздолбайство
- легаси-код
- “так специально задумано”
Не смотря на то, что первые две гипотезы вполне правдоподобны, думаю самый интересный это третий вариант (“так специально задумано”). Если поискать в интернете,то можно найти следующее объяснение.
По “контракту”, который был еще в версиях до женериков, Map должен работать с ключами по следующему правилу:
key==null ? k==null : key.equals(k)
Легко видеть, что т.к. в при вызове метода key.equals(k) объекты key и k потенциально могут быть абсолютно разных классов, то в итоге мы не имеем право вводить ограничение на тип в сигнатуре метода.
Конечно большинство java-программистов знают, что если нужно переопределить метод equals, то по хорошему надо сделать проверку типа проверяемого объекта, но в жизни всякое случается…
В качестве примера к объяснению, в интернете можно встретить пример на списках.
Суть очень простая. Мы предполагаем, что списки равны тогда, когда равны все их элементы. При этом по большому счету не так уж и важно какой именно это список (ArrayList, LinkedList и т.д.).
В итоге если использовать список в качестве ключа, то возникнет следующая (вполне реальная) ситуация.
Map m = new HashMap ();
LinkedList a = new LinkedList();
a.add("1");
a.add("2");
m.put(a, a.size());
// конечно здесь мы явно создаем ArrayList,
// но впринципе нам может вернуться какой-то непонятный список
// из какого-то непонятного метода:
// например List b = doVeryStrangeMethod();
List b = new ArrayList(a);
// Этот вызов метода нормально компилируется и вернет результат:
System.out.println(m.get(b));
// А вот этот вызов приведет к ошибке компиляции, т.к. put с generic-ом
// m.put(b, b.size());
P.S.: Лично я в жизни не сталкивался с ситуацией, когда нужно было использовать список в качестве ключа.