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

我们在上一篇博客中介绍了类实现标记性接口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";
	
	// 构造函数的属性必须是public
	public 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;
	}

	@Override
	public void writeExternal(ObjectOutput paramObjectOutput)
			throws IOException {
		// TODO Auto-generated method stub
		paramObjectOutput.writeObject(name);
		paramObjectOutput.writeDouble(price);
		paramObjectOutput.writeBoolean(status);
		paramObjectOutput.writeInt(rent_days);
		paramObjectOutput.writeObject(list);    
	}


	@Override
	public void readExternal(ObjectInput paramObjectInput) throws IOException,
			ClassNotFoundException {
		// TODO Auto-generated method stub
		name = (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;
	}


	@Override
	public 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 stub
		System.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 execute
create a file: D:\yujie_serialize\yujie_externalizable_book1.txt
file D:\yujie_serialize\yujie_externalizable_book1.txt already exists
Book [name=thinking in java, price=99.99, status=true, rent_days=10, list=[]]
end


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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值