How does java serialization deserialize final fields when no default constructor specified?

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-26 20:51:01

问题


I have an class defining an immutable value type that I now need to serialize. The immutability comes from the final fields which are set in the constructor. I've tried serializing, and it works (surprisingly?) - but I've no idea how.

Here's an example of the class

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...
}

Given that the class doesn't have a no arg constructor, how can it be instantiated and the final field set?

(An aside - I noticed this class particularly because IDEA wasn't generating a "no serialVersionUID" inspection warning for this class, yet successfully generated warnings for other classes that I've just made serializable.)


回答1:


Deserialization is implemented by the JVM on a level below the basic language constructs. Specifically, it does not call any constructor.




回答2:


Given that the class doesn't have a no arg constructor, how can it be instantiated and the final field set?

Some nasty black magic happens. There is a backdoor in the JVM that allows an object to be created without invoking any constructor. The fields of the new object are first initialized to their default values (false, 0, null, etc), and then the object deserialization code populates the fields with values from the object stream.

(Now that Java is open sourced, you can read the code that does this ... and weep!)




回答3:


Both Michael and Stephen gave you an excellent answer, I just want to caution you about transient fields.

If default value (null for references, 0 for primitives ) is not acceptable for them after deserialization then you have to provide your version of readObject and initialize it there.

    private void readObject (
            final ObjectInputStream s
        ) throws
            ClassNotFoundException,
            IOException
    {
        s.defaultReadObject( );

        // derivedValue is still 0
        this.derivedValue = derivedValue( value );
    }


来源:https://stackoverflow.com/questions/2904560/how-does-java-serialization-deserialize-final-fields-when-no-default-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!