序列化和反序列化——试验+理解

测试之前:先明白什么是序列化和反序列化

把对象转化为字节序列的过程成为序列化;

把字节序列恢复为对象的过程成为反序列化;

对象的序列化主要有两种用途:

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

2) 在网络上传送对象的字节序列。

在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。


将要序列的类


import java.io.Serializable;

public class Person implements Serializable{
	  private static final long serialVersionUID = 4603642343377807742L;
	
	    private int age;
	    private String name;

	    public int getAge() {
	        return age;
	    }

	    public void setAge(int age) {
	        this.age = age;
	    }

	    public String getName() {
	        return name;
	    }

	    public void setName(String name) {
	        this.name = name;
	    }

	   
}

测试类:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;

public class TestObjSerializeAndDeserialize {
	public static void main(String[] args) throws Exception {  
        SerializePerson();//序列化Person对象  
//        Person p = DeserializePerson();//反序列Perons对象  
//        System.out.println(MessageFormat.format("name={0},age={1}",  
//               p.getName(), p.getAge()));  
    }  
  
  
    private static void SerializePerson() throws FileNotFoundException, IOException {  
        Person person = new Person();  
        person.setName("gacl");  
        person.setAge(25);  
        // ObjectOutputStream 对象输出流,将Person对象存储到E盘的Person.txt文件中,完成对Person对象的序列化操作  
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("E:/Person.txt")));  
        oo.writeObject(person);  
        System.out.println("Person对象序列化成功!");  
        oo.close();  
    }  
  
    private static Person DeserializePerson() throws Exception, IOException {  
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/Person.txt")));  
        Person person = (Person) ois.readObject();  
        System.out.println("Person对象反序列化成功!");  
        return person;  
    }  
}

测试一:

1、先将反序列代码注掉,进行序列化,序列化成功

2、修改Person的serialVersionUID的值,然后注掉序列化代码,进行反序列化,则会报错Exception in thread "main" java.io.InvalidClassException: com.Person; local class incompatible: stream classdesc serialVersionUID = 4603642343377807741, local class serialVersionUID = 4603642343377807742

测试一结论:

说明serialVersionUID 的值在序列化和反序列化时如果不一样,反序列化则会出错

测试二:

1、Person类不变,测试类的序列化和反序列化代码都放开,则会发现序列化和反序列化都成功

测试二结论:

说明serialVersionUID 的值一直保持一直,反序列就不会被影响

测试三:

在测试2的基础上,不变serialVersionUID 的值,修改Person类,为它添加新的字段,仍然发现序列化和反序列化都成功。

测试三结论:

说明只要serialVersionUID 的值序列和反序列化时保持一直,被序列化的类被更新了同样可以反序列化

测试四:

1、在Person里面不定义private static final long serialVersionUID = 4603642343377807742L;

2、Person保持不变

3、测试类的序列化和反序列化代码都放开,序列化和反序列化都成功

测试四结论:

不更改要被序列化的类时,serialVersionUID的值默认序列化时和反序列化时是一致的

测试五:

1、先序列化原有类Person的对象,并成功

2、在测试四的基础上修改Person的类,为Person添加一个字段

private String tel;
	    
	    public String getTel() {
			return tel;
		}

		public void setTel(String tel) {
			this.tel = tel;
		}

3、再反序列化,发现报错

Exception in thread "main" java.io.InvalidClassException: com.Person; local class incompatible: stream classdesc serialVersionUID = 3388821027241830783, local class serialVersionUID = -5201602265694021977

测试五结论:

如果要反序列化的类在序列化之前反序列化之后进行了修改。serialVersionUID 会发生变化,导致反序列失败

总结:

    开发中每个 实体对象都实现了序列化接口Serializable,而且需要定义serialVersionUID的变量并给出确定的值,因为在开发中实体类的修改是无法避免的事

    序列化的作用是能转化成byte流,然后又能反序列化成原始的类。能在网络进行传输,也可以保存在磁盘中,有了SUID之后,那么如果序列化的类已经保存在本地,中途你修改了类后,SUID变了,那么反序列化的时候就不会变成原始的类了,还会抛出异常。主要用于版本控制

我发现我见过的所有项目(数据库层都是用的mybatis),所有的实体都会实现Serializable接口,如果不实现该接口,对数据库的操作就会报错。所以我判定只要是数据库层用的是mybatis,实体都要实现Serializable接口。跟一个外公司的师父讨论了下,他也没注意这个问题,看了一下他们的代码,果真实现了Serializable接口。开心,学到了一点点

有参考:https://www.cnblogs.com/lqmblog/p/8530108.html

猜你喜欢

转载自blog.csdn.net/Sun_of_Rainy/article/details/88787792