java对象序列化(一)

对象序列化

对象序列化的目标是把对象保存到磁盘中,转化为平台无关的二进制流,从而允许吧这种二进制流持久保存在磁盘上,也可以用过网络传输。程序只要得到了这种二进制流,则可以将这种二进制流转换为Java对象。
为了让某个类是可序列化的,必须实现以下两个类中的任意一个:
Serializable
Externalizable
所有可能在网络上传输的对象的类必须是可序列化的:如RMI,所有需要保存到磁盘的对象也是必须可序列化的,如HttpSession,ServletContext属性的对象

Serializable实现对象的序列化

序列化:1.创建ObjectOutPutStream
     2.调用该流的writeObject方法,输出序列化对象
public class Student implements Serializable{
	private static final long serialVersionUID = 1L;
	private int no;
	private String name;
	public Student(int no, String name) {
		super();
		this.no = no;
		this.name = name;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Student [no=" + no + ", name=" + name + "]";
	}
	
}
public class WriteStudent {
	public static void main(String[] args) throws IOException {
		FileOutputStream outputStream = new FileOutputStream("e://student");
		//创建输出流
		ObjectOutputStream oos = new ObjectOutputStream(outputStream);
		//创建要序列化的对象
		Student student = new Student(1, "jack");
		//输出序列化对象
		oos.writeObject(student);
		oos.close();
	}
}
上面完成了对象的序列化,在输出流的路径可以看到该序列化对象的二进制文件,
如果要恢复该对象,则需要反序列化该对象:
public class ReadStudent {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		FileInputStream in = new FileInputStream("e://student");
		ObjectInputStream ois = new ObjectInputStream(in);
		
		Student student = (Student) ois.readObject();
		System.out.println(student);
		ois.close();
		
	}
}

注意:

1.反序列化读取的是java对象的数据,而不是java类,因此反序列化恢复java对象必须提供该类的class文件,否则引发ClassNotFoundException异常

2.反序列化读取java对象不会调用该类的构造器。

3.当可序列化对象有多个父类是,其父类必须也是可序列化或者有无参的构造器的,如果父类有午餐构造器但是不可序列化,则该父类的成员变量的值不会序列到二进制流中。

4.如果某个类的成员变量不是基本类型,则该引用类必须也是可序列化的,否则引用这个类的类也是不可序列化的

对象引用的序列化

public class Student implements Serializable{
	private static final long serialVersionUID = 1L;
	private int no;
	private String name;
	private Pet pet;
	
	public Pet getPet() {
		return pet;
	}
	public void setPet(Pet pet) {
		this.pet = pet;
	}
	public Student(int no, String name, Pet pet) {
		super();
		this.no = no;
		this.name = name;
		this.pet = pet;
	}
	public Student(int no, String name) {
		super();
		this.no = no;
		this.name = name;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Student [no=" + no + ", name=" + name + ", pet=" + pet + "]";
	}
	
}

两个Student类引用到了同一个Pet对象,序列化该两个Student类只会写入三个对象,pet类不会重复序列化两次
public class StudentTest {
	public static void main(String[] args) throws IOException {
		FileOutputStream outputStream = new FileOutputStream("e://student");
		//创建输出流
		ObjectOutputStream oos = new ObjectOutputStream(outputStream);
		//创建要序列化的对象
		Pet pet = new Pet("tom", "yellow");
		//成员变量引用了同一个对象
		Student student = new Student(1, "jack",pet);
		Student student2 = new Student(2, "rose",pet);
		
		//输出序列化对象
		oos.writeObject(student);
		oos.writeObject(student2);
		
		oos.close();
	}
}
比较两个student类中的pet是同一个类
public class ReadStudent {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		FileInputStream in = new FileInputStream("e://student");
		ObjectInputStream ois = new ObjectInputStream(in);
		
		Student student = (Student) ois.readObject();
		Student student2 = (Student) ois.readObject();
		System.out.println(student);
		System.out.println(student2);
		System.out.println(student.getPet()==student2.getPet());		//输出true
		ois.close();
		
	}
}


java序列化采用的序列化算法:

1.所有保存到磁盘中的对象都有一个序列化编号
2.开始序列化时,判断该对象是否已经被序列化过,如果没有才进行序列化
2.如果序列化过,则只是输出一个序列化编号,不会再次序列化

当序列化一个可变对象时,只有第一次序列化时会转换成字节码输出,以后只会输出一个序列化序号,序列化后修改该对象的实例变量,然后再次序列化,则该实例变量不会改变

public class StudentTest {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		FileOutputStream outputStream = new FileOutputStream("e://pet");
		FileInputStream inputStream = new FileInputStream("e://pet");
		// 创建输出流
		try (ObjectOutputStream oos = new ObjectOutputStream(outputStream);
				ObjectInputStream ois = new ObjectInputStream(inputStream)) {
			// 创建要序列化的对象
			Pet pet = new Pet("tom", "yellow");
			// 输出序列化对象
			oos.writeObject(pet);
			// 修改对象的实例变量的值
			pet.setColor("red");
			oos.writeObject(pet);
			Pet p = (Pet) ois.readObject();
			System.out.println(p);			// color=yellow 不会变为red
		}
	}
}


下一篇:自定义序列化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值