简体   繁体   中英

Java serialization of transient fields

I am reading Thinking in Java 4th Edition . There described a strange workaround for serialization of transient fields:

import java.io.*;

public class SerializationTest implements Serializable {
    private String firstData;
    //transient field, shouldn't be serialized.
    transient private String secondData;

    public SerializationTest(String firstData, String test2) {
        this.firstData = firstData;
        this.secondData = test2;
    }

    /**
     * Private method, same signature as in Serializable interface
     *
     * @param stream
     * @throws IOException
     */
    private void writeObject(ObjectOutputStream stream) throws IOException {
        stream.defaultWriteObject();
        stream.writeObject(secondData);
    }

    /**
     * Private method, same signature as in Serializable interface
     *
     * @param stream
     * @throws IOException
     */
    private void readObject(ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
        secondData = (String) stream.readObject();

    }

    @Override
    public String toString() {
        return "SerializationTest{" +
                "firstData='" + firstData + '\'' +
                ", secondData='" + secondData + '\'' +
                '}';
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream("object.out");
            oos = new ObjectOutputStream(fos);
            SerializationTest sTest = new SerializationTest("First Data", "Second data");
            oos.writeObject(sTest);
        } finally {
            oos.close();
            fos.close();
        }
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = new FileInputStream("object.out");
            ois = new ObjectInputStream(fis);
            SerializationTest sTest = (SerializationTest) ois.readObject();
            System.out.println(sTest);
        } finally {
            ois.close();
            fis.close();
        }
        //Output:
        //SerializationTest{firstData='First Data', secondData='Second data'}
    }
}

As you can see, there are implemented private methods writeObject and readObject .

The questions are:

For what ObjectOutputStream and ObjectInputStream are using Reflection for accessing private methods ?

How many back doors like this are included in the Java ?

Backdoor? It's always been in the spec. It is the only way to implement non-default serialization of an object.

Non-default serialization puts you in the serialization driver's seat. You can write whatever to the output stream and as long as you can read it back and construct your object on the other end of the stream, you'll be ok.

The fact that this person decided to serialize transient fields is just not the issue, the point is that you can do whatever you want if you are implementing your own serialization scheme.

嗯,这不是“后门”……您实现了自定义序列化,该序列化会在调用默认序列化并将其忽略后将瞬态字段输出到输出流。

The Serializable interface is marker interface. So its like a tag to explain the java compiler. There are other marker interfaces like Clonable, etc. See here for more. However now a days @annotations are used more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM