为什么Enum singleton是序列化安全的?

时间:2015-06-05 16:33:52

标签: java serialization enums deserialization hashcode

内部如何在Enum中进行序列化/反序列化? jvm如何在(序列化)之前和之后(反序列化)生成相同的哈希码?

3 个答案:

答案 0 :(得分:6)

序列化专门处理enum。基本上,它只存储对其class的引用和常量的名称。反序列化后,此信息用于查找enum类型的现有运行时对象。

因此,如果在同一运行时中反序列化enum常量,则将获得已序列化的相同运行时实例。

但是,在另一个JVM中反序列化时,哈希码可能会有所不同。但是具有相同的哈希码不是单身人士的必需标准。重要的一点是永远不要有另一个类的实例,这是有保证的,因为序列化实现永远不会创建enum类型的实例,而只会查找现有的常量。

答案 1 :(得分:2)

  

内部如何在Enum中进行序列化/反序列化?

您无法在Java中序列化枚举。您只能序列化对Enum的引用。这意味着如果你的枚举有任何私有字段,它们将不会被写入或恢复。

  

jvm如何在(序列化)之前和之后(反序列化)生成相同的哈希码?

JVM中没有指定JVM如何生成hashCode,实际上是在多个实现的源代码中。但是,Oracle 8更新45 JVM在重新启动后以相同的顺序生成相同的hashCodes。

Object[] objs = new Object[5];
for(int i=0;i<objs.length;i++) {
    objs[i] = new Object();
}
RetentionPolicy[] values = RetentionPolicy.values();
System.out.println(objs+": "+objs.hashCode());
for (Object obj : objs) {
    System.out.println(obj+": "+obj.hashCode());
}
for (RetentionPolicy policy : values) {
    System.out.println(policy+": "+policy.hashCode());
}

如果您使用new Object[5]运行它,则会打印

[Ljava.lang.Object;@677327b6: 1735600054
java.lang.Object@14ae5a5: 21685669
java.lang.Object@7f31245a: 2133927002
java.lang.Object@6d6f6e28: 1836019240
java.lang.Object@135fbaa4: 325040804
java.lang.Object@45ee12a7: 1173230247
SOURCE: 856419764
CLASS: 621009875
RUNTIME: 1265094477

如果我将数组大小减小到2,则会打印出来。

[Ljava.lang.Object;@677327b6: 1735600054
java.lang.Object@14ae5a5: 21685669
java.lang.Object@7f31245a: 2133927002
SOURCE: 1836019240
CLASS: 325040804
RUNTIME: 1173230247

请注意它是如何以相同的顺序生成相同的hashCodes。如果我完全注释掉Object[]代码。

SOURCE: 1735600054
CLASS: 21685669
RUNTIME: 2133927002

每次运行程序时看到相同hashcode的原因是它在检查枚举的hashCodes之前创建了相同数量的hashCodes。

注意:在您要求它降低创建对象的成本之前,对象没有系统hashCode。

答案 2 :(得分:0)

我写了一个简单的枚举类。 例如:

public enum EnumTest{
    
    IND(1),
    ORG(2);
    
    int deger;
    
    EnumTest(int deger){
        this.deger = deger;
    }
    
}

编译这个枚举类后,我们可以使用javap工具使用javap EnumTest命令。

  public final class EnumTest extends java.lang.Enum{
    public static final EnumTest IND;
    public static final EnumTest ORG;
    int deger;
    public static EnumTest[] values();
    public static EnumTest valueOf(java.lang.String);
    static {};
}

从上面的javap工具生成的文本可以看出,枚举实例是静态的,静态变量不能序列化。