Будет ли работать программа без нативного hashCode
Что проверяют
Понимаете ли вы, что native у Object.hashCode() это деталь реализации JVM, а не требование к вашей программе, и знаете ли контракт equals/hashCode. Следом обычно спрашивают, что будет, если переопределить только equals, и как устроен хэш по умолчанию.
Как отвечать
Да, программа будет работать. В Object метод объявлен как public native int hashCode(): его тело написано внутри JVM, а не на Java. Переопределить его своим Java-кодом можно в любом классе, так делают String, Integer, записи (record) и любой класс с Lombok @EqualsAndHashCode. Работу коллекций определяет не «нативность», а контракт:
- согласованность с
equals: равные объекты обязаны возвращать одинаковый хэш; - стабильность: пока не менялись поля, участвующие в
equals, повторные вызовы дают одно число. Между запусками JVM совпадать не обязано; - коллизии разрешены: разные объекты могут иметь одинаковый хэш.
Хэш по умолчанию в HotSpot давно не адрес объекта: объекты двигает сборщик мусора, а хэш обязан быть стабильным. Число генерируется при первом вызове и сохраняется в заголовке объекта. Получить его можно всегда через System.identityHashCode(obj), даже если метод переопределён.
Крайний пример для иллюстрации: return 42; формально соблюдает контракт. HashMap останется корректной, но все ключи лягут в одну корзину. С Java 8 переполненная корзина при достаточно большой таблице превращается в красно-чёрное дерево, но это смягчает деградацию, а не отменяет её.
Где спотыкаются
Повторяют, что хэш по умолчанию это адрес в памяти. Для HotSpot это неверно, и интервьюер часто ловит именно на этом.
Переопределяют equals без hashCode. Компилятор молчит, а HashSet хранит «одинаковые» объекты дважды, и map.get() с новым равным ключом возвращает null.
Считают хэш по изменяемым полям и меняют объект, уже лежащий в HashMap как ключ. Запись остаётся в старой корзине, и найти её по ключу больше нельзя.