[Java学习笔记]IO流——对象流、序列化与反序列化

序列化

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

  • 也就是说:
    把对象转换为字节序列的过程称为对象的序列化。
    把字节序列恢复为对象的过程称为对象的反序列化。

  • 对象的序列化主要有两种用途:   
    1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;   
    2) 在网络上传送对象的字节序列。

ObjectOutputStream类——实现序列化

构造函数:

  • ObjectOutputStream(OutputStream out)
    创建写入指定 OutputStream 的 ObjectOutputStream。

常用API

  • void writeObject(Object obj)
    将指定的对象写入 ObjectOutputStream。
  • 其他字节流共有的write方法(此处不与介绍)

ObjectInputStream类——实现反序列化

构造函数

  • ObjectInputStream(InputStream in)
    创建从指定 InputStream 读取的 ObjectInputStream。

常用API

  • Object readObject()
    从 ObjectInputStream 读取对象。

  • 其他字节流共有的read方法

序列化与反序列化验证
注意:要实现序列化首先肯定需要写入、读出的类实现Serializable接口(无抽象方法,仅作为标记)

	@org.junit.Test
	public void test() throws Exception {
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
		Student s1 = new Student("male",18,"Lily","08194");
		Student s2 = new Student("male",21,"Mike","123132");
		oos.writeObject(s1);
		oos.writeObject(s2);
		Student Lily = (Student) ois.readObject();
		Student Mike = (Student) ois.readObject();
		/*	检验序列化结果 */
		System.out.println(Lily);
		System.out.println(Mike);
//		Student [gender=male, age=18, Name=Lily, Id=08194]
//		Student [gender=male, age=21, Name=Mike, Id=123132]
		
		/*	查看是否为共享空间的同一对象*/
		Lily.setAge(20);
		System.out.println(Lily);//Student [gender=male, age=20, Name=Lily, Id=08194]
		
		System.out.println(s1);//Student [gender=male, age=18, Name=Lily, Id=08194]

		oos.close();
		ois.close();
	}
	//学生实体类
	public class Student implements Serializable{
	//如不指定serialVersionUID在改动类信息时也会变动,倘若序列化和反序列化过程的UID无法匹配则会出现异常
		private static final long serialVersionUID = 1L;
		
		private String gender;
		private int age ;
		private String Name;
		private  String Id;
		public Student() {
		}
	
		@Override
		public String toString() {
			return "Student [gender=" + gender + ", age=" + age + ", Name=" + Name + ", Id=" + Id + "]";
		}

		public Student(String gender, int age, String name,String id) {
			super();
			this.gender = gender;
			this.age = age;
			Name = name;
			Id = id;
		}
	.......
	}

Java的序列化机制
通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

  • 采用在这里插入图片描述这种方式生成的serialVersionUID是1L,
    例如: private static final long serialVersionUID = 1L;

  • 采用在这里插入图片描述这种方式生成的serialVersionUID是根据类名,接口名,方法和属性等来生成的,
    例如:
    private static final long serialVersionUID = 4603642343377807741L;

总结:
在上面的例子中我们发现:

  • Lily.setAge(20);
    System.out.println(Lily);//Student [gender=male, age=20, Name=Lily, Id=08194]
    System.out.println(s1);//Student [gender=male, age=18, Name=Lily, Id=08194]
    改变了反序列化出来的对象,原对象信息不会改变,因此他们不会是同一个对象
    这意味着序列化、反序列化的过程实际上实现了深克隆

序列化与 Transient 关键字

  • Transient 关键字的作用
    控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
  • 父类非serializable的子类对象
    这类子类对象在序列化时不会序列化继承自父类的成员。
    在这里插入图片描述
	@org.junit.Test
	public void test() throws Exception {
		//Serializable : 可序列化的 	 将对象转化成字节的,要求对象必须是可序列化的	仅用于标识可序列化的语义
		//SerialVersionUID
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
		Student s1 = new Student("male",18,"Lily","08194");
		Student s2 = new Student("male",21,"Mike","123132");
		oos.writeObject(s1);
		oos.writeObject(s2);
		Student Lily = (Student) ois.readObject();
		Student Mike = (Student) ois.readObject();
		/*	检验序列化结果 */
		System.out.println(Lily);
		System.out.println(Mike);
		// transient的Id、继承的height\weight都没有被序列化
//		Student [gender=male, age=18, Name=Lily, Id=null, height=0, weight=0]
//		Student [gender=male, age=21, Name=Mike, Id=null, height=0, weight=0]
		oos.close();
		ois.close();
	}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值