哈希码作为 serialVersionUid

Hashcode as serialVersionUid

我在一篇文章中看到,JVM默认提供的serialVersionUid是一个对象的hashcode。如果不覆盖class中的hashcode方法,通常hashcode是object的内存地址,反序列化时如何计算hashcode?

I read in an article that the default serialVersionUid provided by JVM is the hashcode of an object.

这是不正确的。 (要么文章不正确,要么你误读/误解了它。)

可序列化 class 的默认序列版本 UID 与 hashCode 完全无关。

生成默认序列号版本UID的算法如下:

基本上,它根据 classes 名称、修饰符、接口名称及其字段、构造函数和方法的签名创建 SHA-1 哈希。然后它获取散列的前 8 个字节并将它们组装成 long.

我想你误会了。不是hashcodeserialVersionUid 是静态变量,hashcode 是实例方法,对象的哈希码值因对象而异。

serialVersionUid是根据你的class的结构计算出来的——字段、方法等。它在http://download.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html中指定 http://download.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100 确切格式。

规范描述了未提供值时发生的情况,但自动生成使用相同的算法。

流中的项目顺序如下:

  • class 姓名。

  • class修饰符写成32位整数。

  • 每个接口的名称按名称排序。

  • 对于class的每个字段按字段名排序(私有的除外 静态和私有瞬态字段:

    • 字段名称。
    • 写成32位整数的字段修饰符。
    • 字段的描述符。
  • 如果存在 class 初始值设定项,写出以下内容:

    • 方法名称,。
    • 方法的修饰符, java.lang.reflect.Modifier.STATIC,写成32位整数。
    • 方法的描述符,()V.
  • 对于按方法名称和签名排序的每个非私有构造函数:

    • 方法名称,。
    • 方法的修饰符写成32位整数。
    • 方法的描述符。
  • 对于按方法名称和签名排序的每个非私有方法:

    • 方法的名称。
    • 方法的修饰符写成 32 位整数。
    • 方法的描述符。
    • SHA-1 算法在 DataOutputStream 产生的字节流上执行并产生五个 32 位值 sha[0..4]。 散列值由 SHA-1 消息摘要的第一个和第二个 32 位值组合而成。如果消息摘要的结果,即五个 32 位字 H0 H1 H2 H3 H4,在一个名为 sha 的五个 int 值的数组中,则哈希值将计算如下:
    • long hash = ((sha[0] >>> 24) & 0xFF) |

      ((sha[0] >>> 16) & 0xFF) << 8 |

      ((sha[0] >>> 8) & 0xFF) << 16 |

      ((sha[0] >>> 0) & 0xFF) << 24 |

      ((sha[1] >>> 24) & 0xFF) << 32 |

      ((sha[1] >>> 16) & 0xFF) << 40 |

      ((sha[1] >>> 8) & 0xFF) << 48 |

      ((sha[1] >>> 0) & 0xFF) << 56;

这里long hash不是指hashcode