序列化及其代理

参考:http://www.infoq.com/cn/articles/cf-java-object-serialization-rmi


package elevenchapter;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

/*
 * 78:使用序列化代理代替序列化实例类
 */
class Periods implements Serializable {
    private static final long serialVersionUID = -1068352662434111297L;
    private final Date start;
    private final Date end;

    public Periods(Date start, Date end) {
	this.start = new Date(start.getTime());
	this.end = new Date(end.getTime());
	if (start.compareTo(end) > 0)
	    throw new IllegalArgumentException(start + " after " + end);
    }

    public Date start() {
	return start;
    }

    public Date end() {
	return end;
    }

    /*
     * 建立一个内部代理类,域和外围类的域都是一样的
     */
    private static class Proxy implements Serializable {
	private static final long serialVersionUID = -1068352662434111297L;
	private final Date start;
	private final Date end;

	public Proxy(Periods p) {
	    this.start = p.start;
	    this.end = p.end;
	}

	private void writeObject(ObjectOutputStream out) throws IOException {
	    out.defaultWriteObject();
	    System.out.println("proxy writeObject Method run");
	}

	private void readObject(ObjectInputStream in) throws IOException,
		ClassNotFoundException {
	    in.defaultReadObject();
	    System.out.println("proxy readObject Method run");
	}
	// 只要将这个方法返回 periods 就可以了
	private Object readResolve() {
	    System.out.println("proxy readResolve Method run");
	    return new Periods(start,end);
	}
    }

    /*
     * 序列化时会将此方法的返回值进行序列化,而不再是默认的序列
     */
    private Object writeReplace() {
	System.out.println("writeRepalce Method run");
	return new Proxy(this); // 序列化时将 proxy 进行序列化,要想对进进行反序列化进没有出错,就要在 proxy
				// 类中 将 readResolve方法重写,返回一个
				// periods,不然会出错,而外围类的其他序列化方法就不再执行,因为序列化进去的类为
				// proxy
				// 所以后面执行的序列化方法都是 proxy 里面的
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
	out.defaultWriteObject();
	System.out.println("writeObject Method run");
    }

    private void readObject(ObjectInputStream in) throws IOException,
	    ClassNotFoundException {
	in.defaultReadObject();
	System.out.println("readObject Method run");
    }

    private Object readResolve() {
	System.out.println("readResolve Method run");
	return new Periods(start, end);
    }

    public String toString() {
	return String.format("start :%s,end: %s", start, end);
    }

}

public class SevenEight {
    public static void main(String args[]) throws FileNotFoundException,
	    IOException, ClassNotFoundException {
	long start = System.currentTimeMillis();
	long end = System.currentTimeMillis() + 5;
	Periods p = new Periods(new Date(start), new Date(end));
	writeObject(p);
	Periods pp = (Periods) readObject();
	System.out.println(pp.end().getTime()-pp.start().getTime());
    }

    public static void writeObject(Object o) throws FileNotFoundException,
	    IOException {
	ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
		"F:\\singleton.txt"));
	out.writeObject(o);
	out.close();
	System.out.println("对象成功写入...");
    }

    public static Object readObject() throws FileNotFoundException,
	    IOException, ClassNotFoundException {
	ObjectInputStream in = new ObjectInputStream(new FileInputStream(
		"F:\\singleton.txt"));
	Object single = in.readObject();
	in.close();
	System.out.println("对象成功读取...");
	return single;
    }
}
/*
 * Effective java 第78条:	序列化的代理类:
 * 	原是就是在要序列化的类中建立一个 private static class ,内部类与外围类拥有相同 的域,
 * 	这样在外围类序列化的时候,利用  writeReplace 方法返回内部类的实例,将内部类序列化进去,
 * 	这样在反序列化的过程中,就不会再调用外围类的 readObject readRolve 方法,而是调用 内部
 * 	类的这些方法,因为我们序列化进去的是内部类的实例,所以要重写 proxy 类中的 readResolve
 * 	方法,让它在返回的值返回一个 priods 对象
 */


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值