【JAVA】水一下JAVA自有序列化

84 阅读2分钟

原因

网络上查到的太散,用时麻烦。验证下记一下

  1. Serializable接口必须实现;序列化版本号最好指定一个;这是最基础的
  private static final long serialVersionUID = 2659082826995480601L;

后面的点生效优先级递增

  1. transient关键字,不被序列化
  2. JVM隐式约定三个方法用于调整序列化和反序列化

生效强于transient,即即使transient修饰了,也可以自定义将其写入。

直接操作流写入Object时,object内的transient关键字不会生效

执行顺序为:

writeReplace 将序列化对象替换为此方法返回的Object

writeObject 序列化写入后,追加执行一段逻辑,可以追加写入

readObject 反序列化读取后,追加执行一段读取逻辑,对称

private void writeObject(ObjectOutputStream out) throws IOException {
   System.err.println("writeObject");
}

private void readObject(ObjectInputStream ins) throws IOException, ClassNotFoundException {
   System.err.println("readObject");
}

private Object writeReplace(){
   System.err.println("writeReplace");
   return new TestBean();
}
  1. 可以完全自定义序列化逻辑,此时2中的约定方法将不会生效

implements Externalizable

此时2中JVM约定方法不会生效

直接操作流写入Object时,object内的transient关键字不会生效

测试类

package support;

import java.io.*;

/**
 * @author zhengxy.
 * @date 2024/11/11 9:50
 */
public class SerializeTest {


    public static class TestBean
//        implements Serializable
            implements Externalizable {
        @Override
        public String toString() {
            return "age:" + age + "," + "name:" + name;
        }

        private int age = 123;
        private transient String name = "china!";

        private void writeObject(ObjectOutputStream out) throws IOException {
            System.err.println("writeObject");
            //将名字反转写入二进制流
            this.name = name + "america?";
            this.age = 9981;
            out.writeObject(new StringBuffer(this.name));
            out.writeInt(this.age);
        }

        private void readObject(ObjectInputStream ins) throws IOException, ClassNotFoundException {
            System.err.println("readObject");
            //将读出的字符串反转恢复回来
            this.name = ((StringBuffer) ins.readObject()).toString();
            this.age = ins.readInt();
        }

        private Object writeReplace() {
            System.err.println("writeReplace");
            return new TestBean();
        }

        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            System.err.println("writeExternal");
            out.writeObject(this);
//            out.writeObject(new StringBuffer(this.name));
//            out.writeInt(this.age);

        }

        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            System.err.println("readExternal");
            TestBean o = (TestBean) in.readObject();
            this.name = o.name;
            this.age = o.age;
//            this.name = ((StringBuffer) in.readObject()).toString();
//            this.age = in.readInt();

        }

    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        TestBean bean1 = new TestBean();

        File file = new File("bean1.serialize");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(bean1);

        ObjectInputStream inStream = new ObjectInputStream(new FileInputStream("bean1.serialize"));
        TestBean readObject = (TestBean) inStream.readObject();
        System.out.println("反序列化后:" + readObject.toString());
    }
}