InvalidClassException---Serializable小例子

       今天调试项目的时候报了一个InvalidClassException错误。经过调试,发现是服务器和客户端版本不一样,导致某个bean里面的serialVersionUID不一样。今天更新一下博客,复习一下对象的序列化。

        对象要想序列化,就要继承Serializable接口。但是Serializable接口里面没有任何代码。这是因为jvm在序列化对象之前会先做一下instanceof判断。

     student代码:

package codeTest;

import java.io.Serializable;

public class Student implements Serializable{

	private String name;
	private String passwd;
	private Node n;
	private String n1;
	public final String getName() {
		return name;
	}
	public final void setName(String name) {
		this.name = name;
	}
	public final String getPasswd() {
		return passwd;
	}
	public final void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public final Node getN() {
		return n;
	}
	public final void setN(Node n) {
		this.n = n;
	}
	public String toString(){
		return "name:"+this.name+"\t"+"passwds:"+this.passwd+"\t"+"node:"+this.n+"\r\n";
	}
}

 执行代码

Student s = new Student();
		System.out.println(s instanceof Serializable);

 结果为true。

表示这个student类可以被实例化。

node类:

package codeTest;

import java.io.Serializable;

public class Node implements Serializable{
	//节点内容,需要什么加什么
	private String name;  
	//构造函数
	public String toString(){
		return "这是一个node2";
	}
}

 需要注意的是我们要序列化student,就要让student里面的属性也实现序列化接口,如node类。

序列化可以用来做什么?     一般情况下是用来做远程调用的。比如A客户端向B服务器端发送一个类的实例,就是将类的实例序列化成字符流的形式,通过网络传送给B服务器端。服务器端接受到A发来的流,然后强制将其转换为类的实例(当然,发送什么类需要AB协商好.)

    今天的测试小程序就不进行远程接口调用了,今天只测试一个类实例的持久化。白点说就是把一个类实例化,然后将这个实例化的类保存到一个文件里面,然后在读取这个文件,将实例化的类的对象反序列化还原回来。

       序列化student类的方法:

public static void outPut() {
		Student s = new Student();
		s.setName("张三");
		s.setPasswd("123123");
		Node d = new Node();
		s.setN(d);
		try {
			ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("d://test.txt"));
			output.writeObject(s);
			output.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

 反序列化方法:

public static void  inPut(){
		try {
			ObjectInputStream input = new ObjectInputStream(new FileInputStream("d://test.txt"));
			Student s1 = (Student)input.readObject();
			System.out.println(s1);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

 执行序列化方法,可以看到d盘下多了一个test.txt文件,打开发现全是乱码。

执行序列化方法,结果:

name:张三	passwds:123123	node:这是一个node2

 可以看到,反序列化方法把序列化接到的文件给解析出来了。当我们生成一个具体对象,想要传输或者保存时,可以用这种序列化的形式。

      以上的student类没有指定版本号serialVersionUID,那么在jvm进行序列化的时候就会默认生成一个版本号serialVersionUID,在反序列化的时候就会根据这个版本号进行校对,如果不对应的话就会抛出文首提到的那个错误InvalidClassException。serialVersionUID和文件的类型,名字,属性,方法都相关。比如我在student里面加入任意方法或属性,就会报错:

java.io.InvalidClassException: codeTest.Student; local class incompatible: stream classdesc serialVersionUID = 2222222222222222222, local class serialVersionUID = 222221222222222222
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:560)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
	at codeTest.serialVersionTest.inPut(serialVersionTest.java:48)
	at codeTest.serialVersionTest.main(serialVersionTest.java:22)

 但很多时候我们希望对旧版本兼容,就要用到serialVersionUID属性。在student里面加入private static final long serialVersionUID  值可以任意指定。这时候发现,只要serialVersionUID的值不变,不论怎么修改student的其他属性(node的serialVersionUID也要不变),即使将student的其他属性全部删掉,变成

package codeTest;

import java.io.Serializable;

public class Student implements Serializable{
	/**  
	* @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么)  
	*/  
	private static final long serialVersionUID = 222122222222222L;
	
}

 执行反序列化方法结果为:

codeTest.Student@768965fb

 兼容性太强了有么有。。。

如果希望序列化的地方也要更新,那么只需要把版本号改一下就ok了。

猜你喜欢

转载自709002341.iteye.com/blog/2253920