Java学习笔记之IO(十三):对象的序列化和反序列化

package com.io.g_sequence;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.junit.Test;

/*

对象的输入输出流:主要作用是写对象的信息和读取对象的信息; 

	对象的输出流:ObjectOutputStream,将对象数据写出到硬盘上(对象的序列化)
	使用步骤:
		1、找到目标文件
		2、建立数据的输出通道
		3、建立对象的输出流
		4、写出对象数据
		5、关闭资源
	
	对象的输入流:ObjectInputStream,从硬盘上读取对象数据(对象的反序列化)
	使用步骤:
		1、找到目标文件
		2、建立数据的输入通道
		3、建立对象的输入流
		4、读取对象数据
		5、关闭资源
 	
	对象的输入输出流注意事项;
	1、如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口;该接口没有任何方法,是一个标识接口;	
	2、对象的反序列化创建对象的时候并不会调用构造方法;
	3、如果反序列化的时候,User类多了一个字段 int age;那么就会出现异常,异常信息为:
	java.io.InvalidClassException: com.io.g_sequence.User; local class incompatible: stream classdesc 
	serialVersionUID = 8045794779143966462, local class serialVersionUID = 3828153352226528185;
	该异常信息表示:本地的class文件的 serialVersionUID 号与对象输入流里面的 serialVersionUID 号不一致;
	serialVersionUID 是用于记录class文件的版本信息的,serialVersionUID 这个数字是根据类的类名、成员、包名、
	工程名算出的一个数字;
	4、使用ObjectInputStream反序列化的时候,ObjectInputStream会先读取文件中的serialVersionUID,
	然后与本地class文件的serialVersionUID进行对比,如果这两个id不一致,那么反序列化失败;
	5、如果序列化和反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID;如果一个类
	已经指定了serialVersionUID,那么在序列化和反序列化的时候,jvm都不会再去算这个class的serialVersionUID了;
	6、如果一个对象的某个数据不想被序列化到硬盘上,可以使用关键字 transient 修饰;
	7、如果一个类中维护了另外一个类的引用,那么另外一个类也需要实现 Serializable 接口;

 */

// 如果User类中维护了Address类,那么序列化和反序列化的时候Address类也要实现 Serializable 接口;
class Address{
	
	String city;
	String controy;
	
	public Address(String city, String controy) {
		this.city = city;
		this.controy = controy;
	}
	
} 

class User implements Serializable{
	
	String username;
	String password;
//	transient int age; 	// transient:透明
	
	public User(String username, String password) {
		this.username = username;
		this.password = password;
	}
	
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + "]";
	}
	
}

public class Demo3 {

	// 对象的信息在程序执行结束就会删除;
	@Test
	public void test1(){
		User user = new User("张三", "123");
		System.out.println(user);
	}
	
	// 使用对象的输出流将对象信息持久化保存;
	// 把对象的信息写到硬盘上,叫做对象的序列化;
	// 序列化的时候不光将对象信息写入到硬盘上,同时还会将对象所属的class文件的serialVersionUID号,也记录到硬盘上;
	@Test
	public void writeObj() throws IOException{
		// 定义对象信息
		User user = new User("张三", "123");
		// 找到目标文件
		File file = new File("D:\\user.obj");
		// 建立数据的输出通道
		FileOutputStream out = new FileOutputStream(file);
		// 建立对象的输出流对象
		ObjectOutputStream object = new ObjectOutputStream(out);
		// 写出对象数据
		object.writeObject(user);
		// 关闭资源
		object.close();
	}
	
	// 把对象信息从硬盘上读取出来,叫做对象的反序列化;
	@Test
	public void readObj() throws Exception{
		// 找到目标文件
		File file = new File("D:\\user.obj");
		// 建立数据的输入通道
		FileInputStream in = new FileInputStream(file);
		// 建立对象的输入流
		ObjectInputStream object = new ObjectInputStream(in);
		// 读取对象数据
		User user = (User)object.readObject(); // 创建对象依赖对象所属的class文件
		System.out.println(user);
		// 关闭资源
		object.close();
	}
	
}

猜你喜欢

转载自blog.csdn.net/qq_29331365/article/details/78205123