Еще одна причина, по которой он реализован подобным образом, - это то, что я должен представить, что требуется, чтобы hashCode () и equals () были непротиворечивыми, а также для цели разработки Enums, чтобы они были просты в использовании и имели постоянную времени компиляции (для использовать их это "падежные" константы). Это также делает законным сравнение экземпляров enum с "==", и вы просто не хотите, чтобы "equals" вел себя иначе, чем "==" для перечислений. Это снова связывает hashCode со стандартным поведением Object.hashCode () на основе ссылок. Как было сказано ранее, я также не ожидаю, что equals () и hashCode () будут рассматривать две константы enum из разных JVM как равные. Говоря о сериализации: например, поля, типизированные как перечисления, двоичный сериализатор по умолчанию в Java имеет специальное поведение, которое сериализует только имя константы, а при десериализации ссылка на соответствующее значение перечисления в десериализационной JVM воссоздается , JAXB и другие механизмы сериализации на основе XML работают аналогичным образом. Так что: просто не волнуйся
hashCode () в классе Enum является окончательным и определен как super.hashCode (), что означает, что он возвращает число на основе адреса экземпляра, который является случайным числом от программистов POV.
Определение его, например какordinal() ^ getClass().getName().hashCode()
было бы детерминированным в разных JVM. Он даже работал бы немного лучше, поскольку младшие значащие биты «изменились бы настолько, насколько это возможно», например, для перечисления, содержащего до 16 элементов, и HashMap размера 16, наверняка не было бы коллизий (конечно, использование EnumMap лучше, но иногда невозможно, например, нет ConcurrentEnumMap). С нынешним определением у вас нет такой гарантии, не так ли?
С помощьюObject.hashCode()
сравнивается с более хорошим hashCode, подобным приведенному выше, следующим образом:
HashSet
порядок итерацийЯ лично предпочел бы более хороший hashCode, но ИМХО без причины весит много, может быть, кроме скорости.
ОБНОВИТЬМне было любопытно о скорости и написалэталонный тест с удивлениемРезультаты, За цену одного поля на класс вы можете определить детерминированный хэш-код, который почтив четыре раза быстрее, Хранение хеш-кода в каждом поле будет еще быстрее, хотя и незначительно.
Объяснение того, почему стандартный хэш-код не намного быстрее, состоит в том, что он не может быть адресом объекта, поскольку объекты перемещаются GC.
ОБНОВЛЕНИЕ 2Есть некоторые странные вещипродолжается сhashCode
производительность в целом. Когда я понимаю их, все еще остается открытым вопрос, почемуSystem.identityHashCode
(чтение из заголовка объекта) намного медленнее, чем доступ к полям обычного объекта.