java --序列化

#1.序列化与反序列化的概念
将对象转换为字节序列的过程称为对象的序列化。
反过来,将字节序列恢复成对象的过程称为对象的反序列化。
#2.为何要将对象序列化?
2.1当咱们须要将内存中的对象保存到一个文件中/数据库中的时候
一般咱们须要将某些对象进行序列化,让它离开内存空间,入驻物理硬盘,以便长期保存,须要的时候在调取它。例如:缓存,咱们须要将缓存存储起来,须要的时候再将它取出来。
2.2须要在网络上传送对象的时候
当两个进程在进行远程通讯时,彼此时间须要发送数据,不管哪一种类型的数据,都会以二进制序列的形式在网络上传送。
#3.如何实现对象序列化?
很简单,将须要序列化的类实现Serializable接口便可,Serializable接口中没有任何方法。将它理解为一个标记,即代表这个类能够序列化。
#4.实现序列化原理
java.io.ObjectOutputStream表示对象输出流,writeObject(Object obj)方法将指定对象obj写入一个输出流中,即对该对象进行序列化。
java.io.ObjectInputStream表示对象输入流,readObject()方法从ObjectInputStream读取字节序列,再将它们反序列化成为一个对象,并将其返回。
只有实现了Serializable接口的类才能被序列化。对象序列化步骤:
1>建立一个对象输出流,即ObjectOutputStream,它能够包装一个目标输出流,例如文件输出流。
2>调用writeObject(Object obj)方法,参数为obj
对象反序列化过程:
1>建立一个对象输入流,即ObjectInputStream,它能够包装一个源输入流,例如文件输入流。
2>调用readObject()方法读取对象
#5.实例
5.1 定义一个User类并实现Serializablejava

public class User implements Serializable{
	//序列化id
	private static final long serialVersionUID = 1L;

	private Integer id;
        private String name;
}

5.2序列化与反序列化User对象spring

public class TestSerializable {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		//序列化对象
		SerializeUser();
		//反序列化
		User user = DeSerializeUser();
		System.out.println(user);
	}
}

序列化对象代码数据库

/**
	 * 序列化User对象
	 * 1>建立一个对象输出流,即ObjectOutputStream,它能够包装一个目标输出流,例如文件输出流。  
	 * 2>调用writeObject(Object obj)方法,参数为obj  
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	private static void SerializeUser() throws InstantiationException, IllegalAccessException{
		
		//运用反射建立User对象
		User user = new User();
		try {
			Class<?> clazz = Class.forName("com.test.spring.bean.User");
			user = (User) clazz.newInstance();
			user.setId(1001);
			user.setName("张三");
		} catch (ClassNotFoundException e1) {
			System.out.println("没有找到该类");
			e1.printStackTrace();
		}
		//建立对象输出流
		//将User对象序列化,并存储到E盘的Test文件下User.txt文件中
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(new File("E:\\Test\\User.txt")));
			oos.writeObject(user);
			System.out.println("对象序列化成功");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

反序列化代码缓存

/**
	 * 反序列化User对象
	 * 1>建立一个对象输入流,即ObjectInputStream,它能够包装一个源输入流,例如文件输入流。  
	 * 2>调用readObject()方法读取对象  
	 * @throws ClassNotFoundException 
	 */
	private static User DeSerializeUser() throws ClassNotFoundException{
		//new方式建立对象
		User user = new User();
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream(new File("E:\\Test\\User.txt")));
			user = (User) ois.readObject();
			System.out.println("对象反序列化成功");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				ois.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return user;
	}

#6.serialVersionUID
serialVersionUID是序列化版本号,全部实现Serializable接口的类都须要有一个表示序列化版本标识符。
那这个serialVersionUID有什么用呢?
1.咱们去掉User类中的serialVersionUID
输入图片说明
2.在序列化这个类
输入图片说明
3.在User类中添加新的属性
输入图片说明
4.再反序列化User类
报错信息以下网络

java.io.InvalidClassException: com.test.spring.bean.User; local class incompatible: stream classdesc serialVersionUID = 5057804141597769629, local class serialVersionUID = -2824417979782532292

反序列化的过程当中出现问题,报错是stream classdesc serialVersionUID与local class serialVersionUID不一致。
在User类中,若是咱们没有指定serialVersionUID,则java编译器会自动给该类添加一个serialVersionUID;因为没有显式的指定serialVersionUID,全部咱们修改了User类以后,编译器又会给咱们指定一个serialVersionUID,这就出现了两个序列化版本号不一致的错误。
接着测试下有serialVersionUID的状况
1.加上serialVersionUID
2.序列化对象
3.修改对象字段
4.直接反序列化对象
测试了(假设新增属性为age),证实能够反序列化成功,结果以下测试

对象反序列化成功
User [id=1001, name=张三, age=null]
相关文章
相关标签/搜索