2008-10-10 80 views
6

最近出现了一个有趣的问题。我们遇到了正在使用hashCode()为MD5加密盐来源,但由此产生的问题一些代码:在不同的虚拟机相同的对象,不同的JDK版本和操作系统将hashCode()返回相同的值?即使它没有保证,它现在是否有变化?是否可以跨虚拟机,JDK和操作系统使用String.hashCode()?

编辑:我的意思是String.hashCode(),而不是更一般的Object.hashCode(),这当然可以被覆盖。

+0

这个问题实际上让我有点害怕。随机性正是你想要的一个盐源而不是一个一致的实现。为什么不使用Math.random并将结果存储在某个地方? – jsight 2008-10-10 21:35:37

回答

8

号从http://tecfa.unige.ch/guides/java/langspec-1.0/javalang.doc1.html

hashCode的常规合同作为 如下:

  • 每当它是一种 执行的Java应用程序的期间在同一对象上多次调用, hashCode必须始终返回相同的整数 。整数可以是 正数,负数或零。这 整数不,但是,必须 从一个Java的应用程序 保持一致到另一个,或从一个应用 执行到另一个 执行同一应用程序的。 [...]
+1

错了。这适用于java.lang.Object,而不是java.lang.String。后者进一步将规范限制为使用特定的实现。 – Gili 2010-02-12 22:58:53

+0

不应该收回错误的答案吗? – missingfaktor 2015-07-30 14:53:26

0

我想补充一点,你可以重写的hashCode()(不要忘了equals()方法,如果你做到这一点),以确保您的业务对象无处不在返回相同的hashCode 。那些对象至少会有一个可预测的hashCode。

+0

如果您重写hashCode,则不需要重写equals,尽管我不知道为什么要这样做。 – 2008-10-10 08:05:34

3

这取决于类型:

  • 如果你有尚未覆盖的hashCode(A型),那么它将会()每次可能返回不同的hashCode运行程序。
  • 如果你有这样一种类型,重写hashCode(),但不记录它是如何计算的,它是用相同的数据的对象完全合法的,在每个运行返回不同的散列值,只要它返回相同的在同一运行中重复调用散列。
  • 如果你有一类型的覆盖hashCode()方法的记录方式,即算法是记录的行为的一部分,那么你很可能是安全的。 (java.lang.String中的文件本,例如)。但是,我还是会避开的一般原则依靠这种,个人。

从.NET世界只是一个警示:我已经通过使用string.GetHashCode的结果()为数据库中的密码哈希看到至少在痛苦的世界少数人。算法在.NET 1.1和2.0之间改变,突然间所有的哈希值都是“错误的”。 (杰弗里里希特文档通过C#在CLR几乎相同的情况下)。当散列确实被存储需要,我宁愿它的方式是计算总是保证是稳定的 - 例如MD5或由您的类型实现的定制界面,并保证稳定性。

1

号哈希算法不能保证,除非另有规定。因此,例如,哈希结构的反序列化需要重新计算哈希码,并且这些值不应以序列化形式存储。

2

按照docs:作为

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

我不能肯定这是否是一个正式的规范,或只是Sun的实现为一个String对象的哈希码进行计算。至少,在所有现有Sun虚拟机上应该是相同的,无论平台或操作系统如何。

相关问题