Externalizable接口的使用

Externalizable接口

除了Serializable 之外,java中还提供了另一个序列化接口Externalizable

为了了解Externalizable接口和Serializable接口的区别,先来看代码,我们把上面的代码改成使用Externalizable的形式。

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
 
/**
 * 实现Externalizable接口
 */
public class User1 implements Externalizable {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    

    @Override
    public String toString() {
        return "User1 [name=" + name + ", age=" + age + "]";
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        
    }
}

// 测试------------------
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ExternalizableDemo1 {

    // 为了便于理解和节省篇幅,忽略关闭流操作及删除文件操作。真正编码时千万不要忘记
    // IOException直接抛出
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        ObjectOutputStream oos = new ObjectOutputStream(
            new FileOutputStream("tempFile"));
        User1 user = new User1();
        user.setName("张三");
        user.setAge(23);
        oos.writeObject(user);
        oos.close();

        File file = new File("tempFile");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        User1 newInstance = (User1) ois.readObject();
        // output
        System.out.println(newInstance);
        ois.close();
    }
}

通过上面的实例可以发现,对User1类进行序列化及反序列化之后得到的对象的所有属性的值都变成了默认值。也就是说,之前的那个对象的状态并没有被持久化下来。这就是Externalizable接口和Serializable接口的区别

Externalizable继承了Serializable,该接口中定义了两个抽象方法:writeExternal()与readExternal()。当使用Externalizable接口来进行序列化与反序列化的时候需要开发人员重写writeExternal()与readExternal()方法。由于上面的代码中,并没有在这两个方法中定义序列化实现细节,所以输出的内容为空。还有一点值得注意:在使用Externalizable进行序列化的时候,在读取对象时,会调用被序列化类的无参构造器去创建一个新的对象,然后再将被保存对象的字段的值分别填充到新对象中。所以,实现Externalizable接口的类必须要提供一个public的无参的构造器

修改之后代码如下

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

/**
 * 实现Externalizable接口,并实现writeExternal和readExternal方法
 */
public class User2 implements Externalizable {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeInt(age);
    }

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = (String) in.readObject();
        age = in.readInt();
    }

    @Override
    public String toString() {
        return "User2 [name=" + name + ", age=" + age + "]";
    }
}

// -------------------------------------------------
import java.io.*;

public class ExternalizableDemo2 {

    // 为了便于理解和节省篇幅,忽略关闭流操作及删除文件操作。真正编码时千万不要忘记
    // IOException直接抛出
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream("tempFile"));
        User2 user = new User2();
        user.setName("张三");
        user.setAge(23);
        oos.writeObject(user);
        oos.close();

        File file = new File("tempFile");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        User2 newInstance = (User2) ois.readObject();

        System.out.println(newInstance);
        ois.close();
    }
}

这次,就可以把之前的对象状态持久化下来了。

如果User类中没有无参数的构造函数,在运行时会抛出异常:java.io.InvalidClassException

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容