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 接口,被序列化或反序列化时,不会调用对象的构造函数,因此无法完成在构造函数中实现的任何初始化。