📜  Java中的可外部化接口

📅  最后修改于: 2022-05-13 01:54:32.554000             🧑  作者: Mango

Java中的可外部化接口

外部化服务于自定义序列化的目的,我们可以决定在流中存储什么。
Java.io 中存在的 Externalizable 接口用于扩展 Serializable 接口的 Externalization。它由两个方法组成,我们必须重写它们以将对象写入/读取流中/从流中,它们是 -

// to read object from stream
void readExternal(ObjectInput in) 

// to write object into stream
void writeExternal(ObjectOutput out) 

可序列化和可外部化之间的主要区别

  • 实现:与Serializable接口不同,只需实现接口就可以序列化对象中的变量,这里我们必须明确提及您想要序列化的字段或变量。
  • 方法:可序列化是没有任何方法的标记接口。 Externalizable 接口包含两个方法:writeExternal() 和 readExternal()。
  • 过程:默认序列化过程将发生在实现 Serializable 接口的类。程序员为实现 Externalizable 接口的类定义了序列化过程。
  • 向后兼容性和控制:如果您必须支持多个版本,您可以通过 Externalizable 接口进行完全控制。您可以支持不同版本的对象。如果你实现 Externalizable,那么序列化超类是你的责任。
  • public No-arg 构造函数: Serializable 使用反射构造对象,不需要没有 arg 构造函数。但是 Externalizable 需要公共的无参数构造函数。

以下是外部化的示例-

Java
// Java program to demonstrate working of Externalization
// interface
import java.io.*;
class Car implements Externalizable {
    static int age;
    String name;
    int year;
 
    public Car()
    {
        System.out.println("Default Constructor called");
    }
 
    Car(String n, int y)
    {
        this.name = n;
        this.year = y;
        age = 10;
    }
 
    @Override
    public void writeExternal(ObjectOutput out)
        throws IOException
    {
        out.writeObject(name);
        out.writeInt(age);
        out.writeInt(year);
    }
 
    @Override
    public void readExternal(ObjectInput in)
        throws IOException, ClassNotFoundException
    {
        name = (String)in.readObject();
        year = in.readInt();
        age = in.readInt();
    }
 
    @Override public String toString()
    {
        return ("Name: " + name + "\n"
                + "Year: " + year + "\n"
                + "Age: " + age);
    }
}
 
public class ExternExample {
    public static void main(String[] args)
    {
        Car car = new Car("Shubham", 1995);
        Car newcar = null;
 
        // Serialize the car
        try {
            FileOutputStream fo
                = new FileOutputStream("gfg.txt");
            ObjectOutputStream so
                = new ObjectOutputStream(fo);
            so.writeObject(car);
            so.flush();
        }
        catch (Exception e) {
            System.out.println(e);
        }
 
        // Deserialization the car
        try {
            FileInputStream fi
                = new FileInputStream("gfg.txt");
            ObjectInputStream si
                = new ObjectInputStream(fi);
            newcar = (Car)si.readObject();
        }
        catch (Exception e) {
            System.out.println(e);
        }
 
        System.out.println("The original car is:\n" + car);
        System.out.println("The new car is:\n" + newcar);
    }
}


输出:

Default Constructor called
The original car is:
Name: Shubham
Year: 1995
Age: 10
The new car is:
Name: Shubham
Year: 1995
Age: 10

在示例中,类 Car 有两个方法 - writeExternal 和 readExternal。因此,当我们将“Car”对象写入 OutputStream 时,会调用 writeExternal 方法来持久化数据。这同样适用于 readExternal 方法。
重构 Externalizable 对象时,首先使用公共无参数构造函数创建实例,然后调用 readExternal 方法。因此,必须提供无参数构造函数。
当对象实现 Serializable 接口,被序列化或反序列化时,不会调用对象的构造函数,因此无法完成在构造函数中实现的任何初始化。