Externalizable序列化使用

159 阅读2分钟

前言

Serializable接口和Externalizable都用于支持对象的序列化,但是两者在使用上有区别,一定程度上讲,Externalizable接口提供了更加灵活的序列化机制,允许开发者手动控制对象的序列化和反序列化过程

Externalizable使用

Externalizable源码

Externalizable也是一个接口,继承了Serializable接口,定义了writeExternal和readExternal两个方法,用于序列化和反序列化使用,如下图

企业微信截图_17202500338791.png

Externalizable使用

Externalizable序列化更加灵活

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Externalizable {

    private Long id;

    private String name;

    public static void main(String[] args) throws Exception {
        Person person = new Person(1L, "aaa");
        //序列化
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/1.txt"));
        try (out;) {
            out.writeObject(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //反序列化
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/1.txt"));) {
            person = (Person) in.readObject();
            System.out.println(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeLong(id);
        out.writeObject(name);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.id = in.readLong();
        this.name = (String) in.readObject();
    }
}

输出结果为

企业微信截图_17202505417809.png 如果不想序列化id的话,直接把id去掉

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Externalizable {

    private Long id;

    private String name;

    public static void main(String[] args) throws Exception {
        Person person = new Person(1L, "aaa");
        //序列化
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/1.txt"));
        try (out;) {
            out.writeObject(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //反序列化
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/1.txt"));) {
            person = (Person) in.readObject();
            System.out.println(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
//        out.writeLong(id);
        out.writeObject(name);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
//        this.id = in.readLong();
        this.name = (String) in.readObject();
    }
}

Externalizable使用注意

1、使用Externalizable接口之后,之前基于Serializable接口的序列化机制就将失效

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Externalizable, Serializable {

    private Long id;

    private String name;

    public static void main(String[] args) throws Exception {
        Person person = new Person(1L, "aaa");
        //序列化
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/1.txt"));
        try (out;) {
            out.writeObject(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //反序列化
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/1.txt"));) {
            person = (Person) in.readObject();
            System.out.println(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
//        out.writeLong(id);
        out.writeObject(name);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
//        this.id = in.readLong();
        this.name = (String) in.readObject();
    }
}

输出结果为

企业微信截图_17202508369350.png 2、字段被修饰transient的话,如果还在方法内被写入,那么transient也无效

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Externalizable, Serializable {

    private Long id;

    private transient String name;

    public static void main(String[] args) throws Exception {
        Person person = new Person(1L, "aaa");
        //序列化
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/1.txt"));
        try (out;) {
            out.writeObject(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //反序列化
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/1.txt"));) {
            person = (Person) in.readObject();
            System.out.println(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeLong(id);
        out.writeObject(name);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.id = in.readLong();
        this.name = (String) in.readObject();
    }
}

输出结果为

企业微信截图_1720250800194.png 3、不想序列化某字段时,直接不写该字段就行 4、Externalizable读取时,必须按照写入顺序读,否则会报错


@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Externalizable, Serializable {

    private Long id;

    private String name;
    public static void main(String[] args) throws Exception {
        Person person = new Person(1L, "aaa");
        //序列化
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/1.txt"));
        try (out;) {
            out.writeObject(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //反序列化
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/1.txt"));) {
            person = (Person) in.readObject();
            System.out.println(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeLong(id);
        out.writeObject(name);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.name = (String) in.readObject();
        this.id = in.readLong();
    }
}

输出结果为

企业微信截图_17202520482870.png

结论

Externalizable和Serializable都能实现序列化,所以在使用时,根据自己需求实现序列化