当没有指定默认构造函数时,java序列化如何反序列化最终字段?
我有一个类定义了一个不可变的值types,我现在需要序列化。 不变性来自构造函数中设置的最终字段。 我试过序列化,它的工作原理(令人惊讶的是?) – 但我不知道如何。
这是一个类的例子
public class MyValueType implements Serializable { private final int value; private transient int derivedValue; public MyValueType(int value) { this.value = value; this.derivedValue = derivedValue(value); } // getters etc... }
鉴于该类没有arg构造函数,它怎么能被实例化,最终的字段集?
(另外 – 我注意到这个类,特别是因为IDEA没有为这个类生成一个“no serialVersionUID”检查警告,但是成功地为其他类我已经可序列化的警告。)
反序列化由JVM在基本语言结构之下的层次上实现。 具体来说,它不会调用任何构造函数。
鉴于该类没有arg构造函数,它怎么能被实例化,最终的字段集?
一些令人讨厌的黑魔法发生。 JVM中有一个后门,允许创build一个对象而不用调用任何构造函数。 新对象的字段首先被初始化为其默认值(false,0,null等),然后对象反序列化代码使用来自对象stream的值填充字段。
(现在,Java是开源的,你可以阅读这个代码…并哭泣!)
迈克尔和斯蒂芬给了你一个很好的答案,我只是想告诉你关于transient
领域。
如果在反序列化之后默认值(引用为null
,对于基元为0)对于它们来说是不可接受的,那么你必须提供你的readObject
版本并在那里初始化它。
private void readObject ( final ObjectInputStream s ) throws ClassNotFoundException, IOException { s.defaultReadObject( ); // derivedValue is still 0 this.derivedValue = derivedValue( value ); }