Java String.hashCode()是否可以跨VM、JDK和OSs移植?

Java String.hashCode()是否可以跨VM、JDK和OSs移植?,java,hashcode,Java,Hashcode,最近出现了一个有趣的问题。我们遇到了一些使用hashCode()作为MD5加密salt源的代码,但这提出了一个问题:hashCode()是否会在不同的虚拟机、不同的JDK版本和操作系统上为同一对象返回相同的值?即使不能保证,到目前为止,它在任何时候都有变化吗 编辑:我的意思是String.hashCode(),而不是更一般的对象.hashCode(),它当然可以被覆盖。否。来源: hashCode的总合同如下: 如下: 当在一个过程中对同一对象多次调用时 执行Java应用程序, hashCod

最近出现了一个有趣的问题。我们遇到了一些使用
hashCode()
作为MD5加密salt源的代码,但这提出了一个问题:
hashCode()
是否会在不同的虚拟机、不同的JDK版本和操作系统上为同一对象返回相同的值?即使不能保证,到目前为止,它在任何时候都有变化吗

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

否。来源:

hashCode的总合同如下: 如下:

  • 当在一个过程中对同一对象多次调用时 执行Java应用程序, hashCode必须一致地返回 相同的整数。整数可以是 正、负或零。这 然而,整数并不一定要 从一个Java保持一致 应用程序到另一个或从一个 将一个应用程序执行到另一个应用程序 同一应用程序的执行。 [……]

我想补充一点,您可以重写hashCode()(如果这样做,请不要忘记equals()),以确保您的业务对象在任何地方都返回相同的hashCode。这些对象将至少具有可预测的哈希代码。

这取决于类型:

  • 如果您有一个尚未重写hashCode()的类型,那么每次运行程序时,它可能会返回不同的hashCode()
  • 如果您有一个类型覆盖hashCode(),但不记录其计算方式,那么具有相同数据的对象在每次运行时返回不同的哈希值是完全合法的,只要它在同一次运行中为重复调用返回相同的哈希值
  • 如果您有一个类型以文档化的方式重写hashCode(),即算法是文档化行为的一部分,那么您可能是安全的。(例如,java.lang.String记录了这一点。)然而,我个人还是避免根据一般原则依赖这一点

这只是.NET世界的一个警示故事:我见过至少有几个人在痛苦的世界中使用string.GetHashCode()的结果作为他们在数据库中的密码哈希。算法在.NET1.1和2.0之间发生了变化,突然所有的散列都“错了”。(Jeffrey Richter通过C#在CLR中记录了一个几乎相同的案例。)当确实需要存储哈希时,我希望它的计算方式始终保证稳定,例如MD5或由您的类型实现的自定义接口保证稳定。

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

根据:字符串对象的哈希代码计算为

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

我不确定这是正式规范还是Sun的实现。至少,在所有现有的Sun VM上,无论平台或操作系统如何,它都应该是相同的。

如果重写hashCode,则不需要重写equals,尽管我不知道为什么要重写。实际上,这个问题让我有点害怕。随机性正是您希望在salt源中实现的,而不是一致性实现。为什么不直接使用Math.random并将结果存储在某个地方呢?第3点不正确,String.hashCode的实现在Java1.2中发生了变化。Dave:在Java 1.1中,文档没有为String.hashCode指定算法,因此依赖它是不安全的,在Java 1.2中更改它也是可以接受的。该算法现在已明确记录在案——破坏它将违反记录在案的行为。(续)它可以像任何其他记录的行为一样依赖:如果我们不能相信记录的方法行为在API发布之间不会改变,那么我们就注定要失败。这适用于java.lang.Object,而不是java.lang.String。后者进一步将规范限制为特定实现的使用。