java.io.ObjectOutputStream;
public class Myworld {
/**
* @param args
* @throws IOException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {
House house = new House();
System.out.println("序列化前");
Animal animal = new Animal("test",house);
System.out.println(animal);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(animal);
oos.writeObject(animal);//在写一次,看对象是否是一样,
oos.flush();
oos.close();
ByteArrayOutputStream out2 = new ByteArrayOutputStream();//换一个输出流
ObjectOutputStream oos2 = new ObjectOutputStream(out2);
oos2.writeObject(animal);
oos2.flush();
oos2.close();
System.out.println("反序列化后");
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(in);
Animal animal1 = (Animal)ois.readObject();
Animal animal2 = (Animal)ois.readObject();
ois.close();
ByteArrayInputStream in2 = new ByteArrayInputStream(out2.toByteArray());
ObjectInputStream ois2 = new ObjectInputStream(in2);
Animal animal3 = (Animal)ois2.readObject();
ois2.close();
System.out.println("out流:" +animal1);
System.out.println("out流:" +animal2);
System.out.println("out2流:" +animal3);
System.out.println("测试序列化前后的对象 == :"+ (animal==animal1));
System.out.println("测试序列化后同一流的对象:"+ (animal1 == animal2));
System.out.println("测试序列化后不同流的对象==:" + (animal1==animal3));
}
}
运行结果如下:
序列化前
调用了构造器
test[test.serializable.Animal@bb7465']House:test.serializable.House@d6c16c.Create Time is:Sat Apr 06 00:11:30 CST 2013
反序列化后
out流:test[test.serializable.Animal@4f80d6']House:test.serializable.House@193722c.Create Time is:Sat Apr 06 00:11:30 CST 2013
out流:test[test.serializable.Animal@4f80d6']House:test.serializable.House@193722c.Create Time is:Sat Apr 06 00:11:30 CST 2013(与上面的相同)
out2流:test[test.serializable.Animal@12cc95d']House:test.serializable.House@157fb52.Create Time is:Sat Apr 06 00:11:30 CST 2013(与上面只是值相同,但是地址不一样。)
测试序列化前后的对象 == :false
测试序列化后同一流的对象:true
测试序列化后不同流的对象==:false
从结果可以看到
序列化前后对象的地址不同了,但是内容是一样的,而且对象中包含的引用也相同。换句话说,通过序列化操作,我们可以实现对任何可Serializable对象的”深度复制(deep copy)"——这意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。对于同一流的对象,他们的地址是相同,说明他们是同一个对象,但是与其他流的对象地址却不相同。也就说,只要将对象序列化到单一流中,就可以恢复出与我们写出时一样的对象网,而且只要在同一流中,对象都是同一个。
补充:
serialVersionUID 的作用?
在Java中,软件的兼容性是一个大问题,尤其在使用到对象串行性的时候,那么在某一个对象已经被串行化了,可是这个对象又被修改后重新部署了,那么在这种情况下, 用老软件来读取新文件格式虽然不是什么难事,但是有可能丢失一些信息。 serialVersionUID来解决这些问题,新增的serialVersionUID必须定义成下面这种形式:static final long serialVersionUID=-2805284943658356093L;。其中数字后面加上的L表示这是一个long值。 通过这种方式来解决不同的版本之间的串行话问题。
Java串行化机制定义的文件格式似乎很脆弱,只要稍微改动一下类的定义,原来保存的对象就可能无法读取。例如,下面是一个简单的类定义:
public class Save implements Serializable
{
String name;
public void save() throws IOException
{
FileOutputStream f = new FileOutputStream("foo");
ObjectOutputStream oos = new ObjectOutputStream(f);
oos.writeObject(this);
oos.close();
}
}
如果在这个类定义中增加一个域,例如final int val = 7;,再来读取原来保存的对象,就会出现下面的异常:
java.io.InvalidClassException:
Save; local class incompatible:
stream classdesc