【发布时间】:2015-08-20 16:47:11
【问题描述】:
在内部如何在 Enum 中进行序列化/反序列化? jvm如何在(序列化)之前和之后(反序列化)生成相同的哈希码?
【问题讨论】:
标签: java serialization enums deserialization hashcode
在内部如何在 Enum 中进行序列化/反序列化? jvm如何在(序列化)之前和之后(反序列化)生成相同的哈希码?
【问题讨论】:
标签: java serialization enums deserialization hashcode
序列化特别对待enums。基本上,它只存储对其class 的引用和常量的名称。反序列化时,此信息用于查找 enum 类型的现有运行时对象。
因此,如果您在同一运行时内反序列化 enum 常量,您将获得已序列化的同一运行时实例。
但是,在另一个 JVM 中反序列化时,哈希码可能会有所不同。但是具有相同的哈希码并不是单例的必需标准。重要的一点是永远不要拥有该类的另一个实例,这是可以保证的,因为序列化实现永远不会创建 enum 类型的实例,而只会查找现有常量。
【讨论】:
在内部如何在 Enum 中进行序列化/反序列化?
您不能在 Java 中序列化枚举。您只能序列化对枚举的引用。这意味着如果您的枚举有任何私有字段,它们将不会被写入或恢复。
jvm如何在(序列化)之前和之后(反序列化)生成相同的hashcode?p>
在 JLS 中并没有具体说明 JVM 如何生成 hashCode,实际上在源代码中没有指定多个实现。但是Oracle 8 update 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 的原因是它在检查枚举的 hashCode 之前创建了相同数量的 hashCode。
注意:对象没有系统 hashCode,除非您要求它以降低创建对象的成本。
【讨论】:
我写了一个简单的枚举类。 例如:
public enum EnumTest{
IND(1),
ORG(2);
int deger;
EnumTest(int deger){
this.deger = deger;
}
}
编译完这个枚举类后,我们可以通过javap EnumTest命令使用javap工具。
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工具生成的文本可以看出,枚举实例是静态的,静态变量不能序列化。
【讨论】: