最近出现了一个有趣的问题。我们遇到了正在使用hashCode()
为MD5加密盐来源,但由此产生的问题一些代码:在不同的虚拟机相同的对象,不同的JDK版本和操作系统将hashCode()
返回相同的值?即使它没有保证,它现在是否有变化?是否可以跨虚拟机,JDK和操作系统使用String.hashCode()?
编辑:我的意思是String.hashCode()
,而不是更一般的Object.hashCode()
,这当然可以被覆盖。
最近出现了一个有趣的问题。我们遇到了正在使用hashCode()
为MD5加密盐来源,但由此产生的问题一些代码:在不同的虚拟机相同的对象,不同的JDK版本和操作系统将hashCode()
返回相同的值?即使它没有保证,它现在是否有变化?是否可以跨虚拟机,JDK和操作系统使用String.hashCode()?
编辑:我的意思是String.hashCode()
,而不是更一般的Object.hashCode()
,这当然可以被覆盖。
号从http://tecfa.unige.ch/guides/java/langspec-1.0/javalang.doc1.html:
hashCode的常规合同作为 如下:
- 每当它是一种 执行的Java应用程序的期间在同一对象上多次调用, hashCode必须始终返回相同的整数 。整数可以是 正数,负数或零。这 整数不,但是,必须 从一个Java的应用程序 保持一致到另一个,或从一个应用 执行到另一个 执行同一应用程序的。 [...]
错了。这适用于java.lang.Object,而不是java.lang.String。后者进一步将规范限制为使用特定的实现。 – Gili 2010-02-12 22:58:53
不应该收回错误的答案吗? – missingfaktor 2015-07-30 14:53:26
我想补充一点,你可以重写的hashCode()(不要忘了equals()方法,如果你做到这一点),以确保您的业务对象无处不在返回相同的hashCode 。那些对象至少会有一个可预测的hashCode。
如果您重写hashCode,则不需要重写equals,尽管我不知道为什么要这样做。 – 2008-10-10 08:05:34
这取决于类型:
从.NET世界只是一个警示:我已经通过使用string.GetHashCode的结果()为数据库中的密码哈希看到至少在痛苦的世界少数人。算法在.NET 1.1和2.0之间改变,突然间所有的哈希值都是“错误的”。 (杰弗里里希特文档通过C#在CLR几乎相同的情况下)。当散列确实被存储需要,我宁愿它的方式是计算总是保证是稳定的 - 例如MD5或由您的类型实现的定制界面,并保证稳定性。
号哈希算法不能保证,除非另有规定。因此,例如,哈希结构的反序列化需要重新计算哈希码,并且这些值不应以序列化形式存储。
按照docs:作为
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
我不能肯定这是否是一个正式的规范,或只是Sun的实现为一个String对象的哈希码进行计算。至少,在所有现有Sun虚拟机上应该是相同的,无论平台或操作系统如何。
这个问题实际上让我有点害怕。随机性正是你想要的一个盐源而不是一个一致的实现。为什么不使用Math.random并将结果存储在某个地方? – jsight 2008-10-10 21:35:37