前言
Serializable接口和Externalizable都用于支持对象的序列化,但是两者在使用上有区别,一定程度上讲,Externalizable接口提供了更加灵活的序列化机制,允许开发者手动控制对象的序列化和反序列化过程
Externalizable使用
Externalizable源码
Externalizable也是一个接口,继承了Serializable接口,定义了writeExternal和readExternal两个方法,用于序列化和反序列化使用,如下图
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();
}
}
输出结果为
如果不想序列化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();
}
}
输出结果为
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();
}
}
输出结果为
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();
}
}
输出结果为
结论
Externalizable和Serializable都能实现序列化,所以在使用时,根据自己需求实现序列化