Всегда ли у объекта один и тот же hashCode и почему
Что проверяют
Понимаете ли вы, что хеш вычисляется из полей, а не выдаётся навсегда, и знаете ли контракт.
Как отвечать
Нет, не всегда. Контракт требует лишь одного: пока объект не изменился, hashCode обязан возвращать одно и то же значение в пределах одного запуска программы. Между запусками значение может отличаться, и это тоже разрешено.
Разберём случаи:
hashCodeне переопределён: используется реализация изObject, привязанная к идентичности объекта. Два разных объекта с одинаковыми полями дадут разные хеши, а после перезапуска значения будут другими;- переопределён по полям (обычный случай,
data classв Kotlin илиrecordв Java): хеш меняется, как только меняется поле, участвующее в вычислении. Именно поэтому изменяемый объект нельзя класть ключом вHashMap: после изменения он окажется не в той корзине и станет недостижимым; String: хеш стабилен между запусками, потому что вычисляется из символов, и вдобавок кэшируется в поле.
Стоит добавить и обратное: одинаковый хеш не означает равенства. Диапазон int конечен, объектов больше, коллизии неизбежны и допустимы контрактом. Проверка равенства всегда идёт через equals.
Практический вывод: ключами берут неизменяемые объекты, а equals и hashCode считают по одному и тому же набору полей.
Где спотыкаются
Считают хеш вечным идентификатором объекта.
Кладут ключом изменяемый объект и теряют значения в карте.
Уверены, что одинаковый хеш означает равенство.
Полагаются на стабильность хеша между запусками и сохраняют его в базу.