当没有指定默认构造函数时,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 ); }