java为什么我看到枚举常量的字段值会被序列化/反序列化?在哪种情况下,枚举中哪些内容没有序列化?
Serialization Specification(SE8)意味着枚举常量的字段值没有序列化(正如我读到的):
1.12 Serialization of Enum Constants Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form.
但我看到它们确实被序列化/反序列化了
在下面的代码中,枚举常量的public int x = 1234;
字段INSTANCE
在两种情况下被序列化/反序列化:
- 仅在构造函数中设置(在
public int x = 1234;
之后,setX()
方法从未调用),然后成功地反序列化x = 1234
李> - 在构造函数之后,我调用
setX(7)
,但该设置值(x=7
)随后被成功反序列化李>
那么在什么情况下,枚举中不序列化/反序列化那么“形式”这个词是什么意思呢
enum MyEnum1 {
INSTANCE {
public int x = 1234;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
};
public abstract int getX();
public abstract void setX(int x);
}
public class AAA {
public static void main(String[] args) {
MyEnum1 obj = MyEnum1.INSTANCE;
obj.setX(7);
System.out.println(obj.getX());
String fileName = "d:\\del.me";
int bufSz = 8 * 1024;
try {
ObjectOutputStream oos = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(fileName), bufSz));
oos.writeObject(obj);
oos.flush();
} catch (IOException e) { }
MyEnum1 obj1 = null;
MyEnum1 obj2 = null;
try {
ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(new FileInputStream(fileName), bufSz));
ObjectInputStream ois1 = new ObjectInputStream(
new BufferedInputStream(new FileInputStream(fileName), bufSz));
obj1 = (MyEnum1) ois.readObject();
obj2 = (MyEnum1) ois1.readObject();
} catch (IOException | ClassNotFoundException e) { }
// x is restored, either the one set by setX()
// or the one just set in inline constructor (initializer) without calling setX()
System.out.println(obj1.getX()); // 1234 without setX(7), 7 with setX(7)
System.out.println(obj2.getX()); // 1234 without setX(7), 7 with setX(7)
}
}
p.S.This answer对我来说还意味着枚举常量中的字段不会被序列化:
As I see it, it doesn't make sense to mark Enum's field values as transient or make them implement Serializable, since they'll never get serialized, no matter if they're marked as transient or implement Serializable.
但在我看来,enum常量内(如Color { RED { fields }; }
或enum内但“在”每个单独常量外(Color { RED { fields }; fields_for_all_constants}
)的所有(非瞬态)字段(至少是原始字段)都会被序列化
# 1 楼答案
您的测试存在缺陷,因为它假定反序列化枚举常量会导致枚举常量的多个实例。来自JLS的§8.9(强调我的):
这意味着在
MyEnum1.INSTANCE
上设置x
会全局更改值,就像更改“常规”单例的状态一样。当反序列化常量时,会得到已经存在的相同实例,,这意味着它的当前值为^{更好的测试是在程序的一次运行中序列化常量,然后在后续运行中反序列化。请尝试以下示例:
首先运行
java Main save
将枚举常量序列化为文件。然后执行java Main load
,它将反序列化枚举常量并打印value
。尽管在value
为10
时序列化了enum常量,但反序列化实例的value
为5
(初始值)。这强烈表明字段没有与enum常量一起序列化代码创建一个单个JVM实例,该实例设置值,序列化枚举,然后反序列化枚举。由于这一切都发生在同一个JVM中,因此反序列化的枚举将是已经存在且
x
已更改的同一个实例我的代码有两种模式:“保存”和“加载”
value
,然后将枚举序列化为一个文件value
这两种模式不能在程序的一次调用中发生,这意味着每种模式都使用不同的JVM实例。因为这发生在两个不同的JVM实例上,所以反序列化的enum不是序列化的同一个实例