1.Externalizable接口介绍
Java序列化除了Serializable接口之外,还有一个Externalizable接口,Externalizable是Serializable的子类。如果一个类实现了Serializable接口,那么序列化的工作是java自己完成的。如果我们自定义序列化工作,那么可以实现Externalizable接口。
Externalizable接口有两个待实现的方法writeExternal和readExternal,具体如下。
public interface Externalizable extends Serializable {
// 通过实现该方法,实现对象的自定义序列化
void writeExternal(ObjectOutput out) throws IOException;
// 通过实现该方法,实现对象的自定义反序列化
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
2. 举例
实现Externalizable接口的类,必须有public的无参构造器,因为在这种序列化机制中,需要构造器参与。
public class User implements Externalizable {
private String name;
private transient String password;
// 必须要有无参构造器
public User() {
System.out.println("constructor");
}
// 序列化User对象
public void writeExternal(ObjectOutput out) throws IOException {
System.out.println("writeExternal");
out.writeObject(name);
out.writeObject(password);
}
// 反序列化User对象
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
System.out.println("readExternal");
name = (String) in.readObject();
password = (String) in.readObject();
}
// 不会被执行
private void writeObject(ObjectOutputStream out) throws IOException {
System.out.println("writeObject");
}
// 不会被执行
private void readObject(ObjectInputStream in) throws IOException {
System.out.println("readObject");
}
// 在writeExternal之前执行,只是为了说明执行顺序,实际不需要写。
private Object writeReplace() throws ObjectStreamException {
this.setName("kobe");
System.out.println("writeReplace");
return this;
}
// 在readExternal之后执行,只是为了说明执行顺序,实际不需要写。
private Object readResolve() throws ObjectStreamException {
this.setName("kobe");
System.out.println("readresolve");
return this;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
3. 和Serializable接口对比
Serializable开发相对简单,Externalizable需要我们自行实现序列化和反序列化。
网上有的文章说相比Serializable,Externalizable序列化的速度更快,而且数据更小。根据本人的测试,Externalizable序列化后的文件确实小,但速度却没有Serializable快。
不管如何,Externalizable给了我们另外一种控制序列化的方式。
测试的办法是:两个相同内容的User类,一个实现Serializable接口,一个实现Externalizable接口,然后使用ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream());
循环写出去n次。无论n=1000、1w、10w,都是Serializable接口更快一些。
4. 方法在什么时候被调用
我们在User类中实现的writeExternal和readExternal方法,是在ObjectOutputStream和ObjectInputStream中被调用的。以writeExternal为例,其调用的方法顺序如下:
1.ObjectOutputStream.writeObject(Object obj)
2.ObjectOutputStream.writeObject0(Object obj, boolean unshared)
3.ObjectOutputStream.writeOrdinaryObject(Object obj,
ObjectStreamClass desc,
boolean unshared)
4.ObjectOutputStream.writeExternalData(Externalizable obj)
5.User.writeExternal(ObjectOutput out)
(完)
网友评论