Serializable 和 serialVersionUID

如果需要使用ObjectInputStream和ObjectOuputStream的readObject以及writeObject()方法写入和读取非Java的基础类,需要对该类进行序列化。
例如,如果需读写String,数组,枚举类型以及Java的基本数据类型,
则不需要做其他额外操作可以直接使用readObject()和writeObject()方法读取。
如果是自己创建的Class,那就不行啦,会得到一个NotSerializableException。

比如下面的代码:

import java.io.*;

public class TestObjectIO {

	public static void main(String[] args) {
		T t=new T();
		t.i=10;
		int a[] = {1,2,3};
		try {
			FileOutputStream fos=new FileOutputStream("d:/Java/io.dat");
			ObjectOutputStream oos=new ObjectOutputStream(fos);
			oos.writeObject(t);
			oos.writeObject(a);
			oos.flush();
			
			
			oos.close();
			
			
			FileInputStream fis=new FileInputStream("d:/Java/io.dat");
			ObjectInputStream ois=new ObjectInputStream(fis);
			
			T tread=(T)ois.readObject();
			int b[] = (int [])ois.readObject();
			
			System.out.println(tread);
			System.out.println(tread.i+" "+tread.b+" "+tread.d+" "+tread.f);
			System.out.println("b [] :"+b[0]+b[1]+b[2]);
			
			//ois.fulsh();
			ois.close();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

	}

}
class T implements Serializable{
	public static final long serialVersionUID = 2862048673777473868L;
	
	int i=8;
	double d=1.0;
	boolean b=true;
	transient float f=1.8f; //transient 表示不进行序列化
	public String toString(){
		return "int i= "+i+"\ndouble d= "+d+"\nboolean b= "+b+"\nfloat f= "+f;
	}
}

解决方法呢,就是给myClass类加上implements Serializable接口。

实现Serializable接口的没有任何额外要求,但是有一个建议就是在类中指定一个SerializableUID。
SerializableUID的用途如下:
1,写myClass对象的时候(writeObejct方法中)将这个SerializableUID首先写在流中,之后是myClass的bye流。
2,在读取myClass对象的时候(readObject()方法中)首先读出这个SerializableUID,之后在JavaVM中检索是否存在和这个UID对应的实现了Serializable接口的类。如果存在,则正常读出一个该类的实例,否则会收到一个InvalidClassException。
PS:指定UID的时候要注意,不支持Serializable接口的所有Class默认的SerializableUID都是0L(long型哦!)。

当然,建议终究是建议,如果不指定的话java.io.ObjectStreamClass类中提供了computeDefaultSUID()方法给没有SerializableUID又实现了Serializable接口的Class计算一个默认的SerializableUID,在写的时候(writeObejct方法中)会算一下写到流中,读的时候(readObject()方法中)再算一下看看是否相等。
具体实现方式可以参考java.io.ObjectStreamClass类,基本上还是按照类的结构,还有参数内容,类型计算出来的,尽量保证(不一定肯定能保证,推荐你自己写一个都...)不会出现类不一样UID一样的情况。

Java.io.ObjectStreamClass这个类感觉是为序列化专用的类,主要作用就是和JavaVM通信,里面的一个方法lookup()非常有用,用于检查在当前VM中是否存在某个类。在读取对象的时候就是使用这个方法的。

Java实现类的序列化不仅有Serializable,还有Externalizable接口,Externalizable是Serializable的子接口。实现Externalizable必须手动实现readExternal和writeExternal两个方法,在读写对象的时候会调用这两个方法进行对象的读写。如果继承的是Serializable接口,读些对象的时候调用的就是writeObject()和readObject()方法了。

如果想控制对象是如何序列化的,那么就用Externalizable吧!


//转载http://blog.csdn.net/eadber/article/details/2347167

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值