java序列化与反序列化(3)------jdk原生序列化机制Externalizable

来源:互联网 发布:免费邮件服务器软件 编辑:程序博客网 时间:2024/06/06 00:04

我们在上一篇博客中介绍了类实现标记性接口Serializable来实现序列化,但是如果你只想序列化诸多域中的某几个域,一种选择是将不序列化的域都标记上transient关键字,但是如果不需要序列化的域比较多,那么这种方式看起来很麻烦呀,第二种选择就是实现Externalizable接口了。这个接口其实是继承自Serializable接口,继承Externalizable的类必须实现writeExternal(ObjectOutput paramObjectOutput)和readExternal(ObjectInput paramObjectInput)两个方法,之后在序列化和反序列化是jdk序列化代码会判断是否是实现Externalizable接口的类,如果是的话序列化是就会调用writeExternal方法,反序列化时就会调用readExternal,这样我们就必须负责类的序列化所有的细节。

public abstract interface Externalizable extends Serializable {public abstract void writeExternal(ObjectOutput paramObjectOutput)throws IOException;public abstract void readExternal(ObjectInput paramObjectInput)throws IOException, ClassNotFoundException;}

当然如果想正常的序列化除了实现上述两个方法之后,实现Externalizable接口的类必须提供一个公共的无参构造函数,在反序列化时会调用这个无参构造函数创建一个对象,之后再调用readExternal方法为域设置域值。

我们的测试代码如下:

/** * 实现Externalizable接口的类 必须提供一个无参的公共构造函数 * @author yujie.wang * @since 10/4/2017 */public class Book_Externalizable implements Externalizable {//序列化的版本号private static final long serialVersionUID = 6165984730624879548L;private String name; private double price;private boolean status;private int rent_days;private List<String> list;// 静态域属于类,不是对象的状态private static String note = "this is a nice book";// 构造函数的属性必须是publicpublic Book_Externalizable(){}public Book_Externalizable(String name, double price, boolean status, int rent_days, List<String> list){this.name = name;this.price = price;this.status = status;this.rent_days = rent_days;this.list = list;}@Overridepublic void writeExternal(ObjectOutput paramObjectOutput)throws IOException {// TODO Auto-generated method stubparamObjectOutput.writeObject(name);paramObjectOutput.writeDouble(price);paramObjectOutput.writeBoolean(status);paramObjectOutput.writeInt(rent_days);paramObjectOutput.writeObject(list);    }@Overridepublic void readExternal(ObjectInput paramObjectInput) throws IOException,ClassNotFoundException {// TODO Auto-generated method stubname = (String)paramObjectInput.readObject();price = paramObjectInput.readDouble();status = paramObjectInput.readBoolean();rent_days = paramObjectInput.readInt();list = (List<String>)paramObjectInput.readObject();}public static String getNote() {return note;}public static void setNote(String note) {Book_Externalizable.note = note;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public boolean isStatus() {return status;}public void setStatus(boolean status) {this.status = status;}public int getRent_days() {return rent_days;}public void setRent_days(int rent_days) {this.rent_days = rent_days;}public List<String> getList() {return list;}public void setList(List<String> list) {this.list = list;}@Overridepublic String toString() {return "Book [name=" + name + ", price=" + price + ", status=" + status+ ", rent_days=" + rent_days + ", list=" + list+ "]";}}



测试工具类:

/** * 序列化测试工具 * @author yujie.wang * */public class Externalizable_Main {private static FileInputStream fin;private static FileOutputStream fout;private static String prefix_Path = "D:\\yujie_serialize\\yujie_externalizable_book";private static String suffix_file_name = ".txt";public static void main(String[] args) throws IOException, ClassNotFoundException {// TODO Auto-generated method stubSystem.out.println("begin to execute");Book_Externalizable book = new Book_Externalizable("thinking in java", 99.99, true, 10, new ArrayList<String>());String filePathName = getFileFullPathName("1");//执行序列化serializeObject(book,filePathName );//执行反序列化过程deSerializeObject(filePathName);System.out.println("end");}/** * 反序列化 * @param fileName * @throws IOException * @throws ClassNotFoundException */public static void deSerializeObject(String fileName) throws IOException, ClassNotFoundException{File file = createFile(fileName);if(file == null)return;fin = new FileInputStream(file);ObjectInputStream ois = new ObjectInputStream(fin);Book_Externalizable book = (Book_Externalizable)ois.readObject();if(book == null) {    System.out.println("boo == null");} else {System.out.println(book.toString());}}/** * 序列化一个对象 * @param book * @param fileName * @throws IOException */public static void serializeObject(Book_Externalizable book, String fileName) throws IOException{File file = createFile(fileName);if(file == null)return;fout = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fout);oos.writeObject(book);oos.flush();oos.close();fout.close();}/** * 创建一个文件 * @param fileName * @return * @throws IOException */public static File createFile(String fileName) throws IOException{if(fileName == null || fileName.isEmpty())return null;File file = new File(fileName);if(!file.exists()){file.createNewFile();System.out.println("create a file: "+ fileName);} else {System.out.println("file "+ fileName + " already exists");}return file;}/** * 获得一个全路径的文件名 * @param fileName * @return */public static String getFileFullPathName(String fileName){return prefix_Path + fileName +suffix_file_name;}}

运行测试工具类代码输出结果:

begin to executecreate a file: D:\yujie_serialize\yujie_externalizable_book1.txtfile D:\yujie_serialize\yujie_externalizable_book1.txt already existsBook [name=thinking in java, price=99.99, status=true, rent_days=10, list=[]]end


总结一下实现Externalizable接口的序列化方法:

(1)自己手动实现writeExternal和readExternal方法

(2)实现Externalizable接口的类必须提供一个公共的无参构造函数

阅读全文
0 0
原创粉丝点击