Является ли String.hashCode () переносимым на виртуальные машины, JDK и ОС? - PullRequest
6 голосов
/ 10 октября 2008

Интересная проблема возникла недавно. Мы натолкнулись на некоторый код, который использует hashCode() в качестве основного источника для шифрования MD5, но возникает вопрос: будет ли hashCode() возвращать одно и то же значение для одного и того же объекта на разных виртуальных машинах, разных версиях JDK и операционных системах? Даже если это не гарантировано, изменилось ли оно в какой-то момент до настоящего времени?

РЕДАКТИРОВАТЬ: я действительно имею в виду String.hashCode(), а не более общий Object.hashCode(), который, конечно, может быть отменен.

Ответы [ 5 ]

8 голосов
/ 10 октября 2008

Нет. От http://tecfa.unige.ch/guides/java/langspec-1.0/javalang.doc1.html:

Общий контракт hashCode: следующим образом:

  • Всякий раз, когда он вызывается для одного и того же объекта более одного раза в течение выполнение приложения Java, hashCode должен последовательно возвращать то же самое целое число. Целое число может быть положительный, отрицательный или ноль. это целое число, однако, не должно оставаться последовательным с одной Java приложение к другому или от одного оформление заявления другому исполнение того же приложения. [...]
3 голосов
/ 10 октября 2008

Зависит от типа:

  • Если у вас есть тип, который не переопределяет hashCode (), то он, вероятно, будет возвращать новый hashCode () каждый раз, когда вы запускаете программу.
  • Если у вас есть тип, который переопределяет hashCode (), но не документирует, как он рассчитывается, то вполне допустимо, чтобы объект с одинаковыми данными возвращал разный хеш при каждом запуске, если он возвращает тот же самый хэш для повторных вызовов в пределах одной и той же серии.
  • Если у вас есть тип, который переопределяет hashCode () документированным образом, то есть алгоритм является частью документированного поведения, то вы, вероятно, в безопасности. (java.lang.String документирует это, например.) Тем не менее, я все же держусь подальше от , полагаясь на это по общему принципу, лично.

Просто предостерегающая история из мира .NET: я видел по крайней мере несколько человек в мире боли, когда использовал результат string.GetHashCode () в качестве хэша своего пароля в базе данных. Алгоритм изменился между .NET 1.1 и 2.0, и внезапно все хеши оказались «неправильными». (Джеффри Рихтер документирует почти идентичный случай в CLR с помощью C #.) Когда хэш требует необходимости хранения, я бы предпочел, чтобы он вычислялся так, чтобы всегда гарантировался быть стабильным - например MD5 или пользовательский интерфейс, реализованный вашими типами с гарантией стабильности.

2 голосов
/ 10 октября 2008

Согласно документам : хеш-код для объекта String вычисляется как

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

Я не уверен, является ли это формальной спецификацией или просто реализацией Sun. По крайней мере, оно должно быть одинаковым на всех существующих виртуальных машинах Sun независимо от платформы или операционной системы.

1 голос
/ 10 октября 2008

Нет. Хеш-алгоритмы не гарантируются, если не указано иное. Так, например, десериализация хеш-структур должна пересчитывать хеш-коды, и эти значения не должны храниться в сериализованной форме.

0 голосов
/ 10 октября 2008

Я хотел бы добавить, что вы можете переопределить hashCode () (не забывайте equals (), если вы это сделаете), чтобы ваши бизнес-объекты везде возвращали одинаковый hashCode. Эти объекты будут, по крайней мере, иметь предсказуемый hashCode.

...