有关Java序列化(三)——使用Externalizable
JDK中提供了另一个序列化接口--Externalizable,使用该接口之后,之前基于Serializable接口的序列化机制就将失效。Externalizable继承于Serializable,当使用该接口时,序列化的细节需要由程序员去完成。
测试代码:
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class Person implements Externalizable {
private static final long serialVersionUID = -842029427676826563L;
public static String name;
private int age;
private transient int workDay = 5;
private String fClub;
public Person() {
System.out.println("none-arg constructor");
}
public Person(int age, String fClub) {
this.age = age;
this.fClub = fClub;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWorkDay() {
return workDay;
}
public void setWorkDay(int workDay) {
this.workDay = workDay;
}
public String getfClub() {
return fClub;
}
public void setfClub(String fClub) {
this.fClub = fClub;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();//执行默认的序列化机制
out.writeInt(workDay);
System.out.println("正在进行序列持久化");
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
workDay = in.readInt();
System.out.println("读取持久化对象");
}
@Override
public void readExternal(ObjectInput arg0) throws IOException,
ClassNotFoundException {
// TODO Auto-generated method stub
}
@Override
public void writeExternal(ObjectOutput arg0) throws IOException {
// TODO Auto-generated method stub
}
}
主测试类代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Hello {
public static void main(String[] args) {
Person person = new Person(26, "Juventus");
person.setWorkDay(7);
try {
FileOutputStream fs = new FileOutputStream("foo.ser");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(person);
os.close();
Person.name = "Alex";
FileInputStream in = new FileInputStream("foo.ser");
ObjectInputStream s = new ObjectInputStream(in);
Person p = (Person) s.readObject();
System.out.println("name==" + Person.name + " age==" + p.getAge()
+ " workDay==" + p.getWorkDay() + " fClub==" + p.getfClub());
} catch (Exception e) {
e.printStackTrace();
}
}
}
程序输出为:
none-arg constructor name==Alex age==0 workDay==5 fClub==null
从结果来看,writeObject和readObject没再被执行,Person p = (Person) s.readObject()读取持久化类的时候调用了Person的无参构造函数。同时发现,foo.ser文件里只有类的类型声明,没有任何实例变量,Person对象中任何一个字段都没有被序列化,所以打印结果里面,age为0,fClub为null,而workDay为初始值5。
如上所示的代码,由于writeExternal()与readExternal()方法未作任何处理,那么该序列化行为将不会保存/读取任何一个字段。
更改Person类:
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class Person implements Externalizable {
private static final long serialVersionUID = -842029427676826563L;
public static String name;
private int age;
private transient int workDay = 5;
private String fClub;
public Person() {
System.out.println("none-arg constructor");
}
public Person(int age, String fClub) {
this.age = age;
this.fClub = fClub;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWorkDay() {
return workDay;
}
public void setWorkDay(int workDay) {
this.workDay = workDay;
}
public String getfClub() {
return fClub;
}
public void setfClub(String fClub) {
this.fClub = fClub;
}
/*//writeObject和readObject不再被执行
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();//执行默认的序列化机制
out.writeInt(workDay);
System.out.println("正在进行序列持久化");
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
workDay = in.readInt();
System.out.println("读取持久化对象");
}
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(fClub);
out.writeInt(age);
System.out.println("自定义序列化过程");
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
fClub = (String) in.readObject();
age = in.readInt();
System.out.println("自定义反序列化");
}
}
主测试程序的输出结果为:
自定义序列化过程
none-arg constructor
自定义反序列化
name==Alex age==26 workDay==5 fClub==Juventus
使用Externalizable进行序列化,当读取对象时,会调用被序列化类的无参构造器去创建一个新的对象,然后再将被保存对象的字段的值分别填充到新对象中。这就是为什么输出结果中会显示调动了无参构造器。由于这个原因,实现Externalizable接口的类必须要提供一个无参的构造器,且它的访问权限为public。
参考:
http://www.blogjava.net/jiangshachina/archive/2012/02/13/369898.html
上一篇: MongoDB操作类封装实例代码
下一篇: Serializable的过程分析
推荐阅读
-
ElasticSearch实战系列三: ElasticSearch的JAVA API使用教程
-
Java序列化与反序列化三连问:是什么?为什么要?如何做?
-
详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)
-
使用Java实现数据库编程—03 第三章 高级查询(一)
-
解决Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)的序列化问题
-
json的介绍(三)----json在java的使用
-
json的介绍(三)----json在java的使用
-
Java NIO 入门(三)从理论到实践:使用NIO读写
-
Java爬虫系列三:使用Jsoup解析HTML
-
荐 Java中多线程的使用(超级超级详细)线程安全+线程锁原理解析+保证线程安全的三种方式 (同步代码块+同步方法+lock锁) 5