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类并实现Serializable

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

	private Integer id;
        private String name;
}

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

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]

转载于:https://my.oschina.net/u/2312022/blog/752064

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值