(杂记)Java序列化Serializable和反序列化

1.什么是java序列化?

把对象转化为字节序列的过程称为序列化
把字节序列转化为对象的过程称为反序列化。

2.为什么需要序列化?

序列化主要有两个应用场景:
  1. 用于把对象从内存中保存到磁盘中。
  2. 用于网络上传输对象

    此处举例解释一下:
    比如Web开发中经常遇到的Session对象存储问题,假设有10W个并发请求到来,内存短时间内生成10W个Session对象是吃不消的,怎么办呢?先把这10W个Session对象永久性地保存到磁盘,那么短时间内,根据到来的请求,逐个在内存中还原Session对象,此时,在磁盘里保存的最好的是Java序列化对象,最小化占据磁盘内存。
    再说远程网络通信,网络上数据都是二进制序列形式,一般请求方会发送java对象的字节序列,接收方根据字节序列还原java对象。好处是什么?对象的字节序列内存远小于对象内存,可以缩短请求-响应耗时。
注意事项
3. 假如对象中包含有对象属性,那么该对象的类也要实现Serializable接口,否则该对象无法实现序列化。 4. 序列化操作会忽略静态变量的状态,举例说对象中的static属性不能被序列化,static属性是类级别的,不是对象级别的。

3.序列化过程与代码示例

首先介绍一下要用到的JDK类库中的API:

1.java.io.OutputStream对象输出流,通过该类(或其子类FileOutputStream,ByteOutputStream)创建一个可被序列化的对象,然后将该对象传递给java.io.ObjectOutputStream对象,该对象的writeObject()方法接受一个OutputStream对象,完成序列化过程。
2.java.io.InputStream对象输入流,接受一个对象输入流,然后调用java.io.ObjectInputStream.readObject()方法,完成发序列化。(详见代码栗子)


java序列化对象代码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerializeInstance implements Serializable {

	/**
	 * the default serialVersion UID;
	 */
	private static final long serialVersionUID = 1L;
	public int num = 1209;
	public static void main(String []args)   {
		try {
			//1.the process of the serializing 
			FileOutputStream fileOutputStream = new FileOutputStream("D:\\JavaCodes\\Examps\\JasonWord.txt");
			ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
			 SerializeInstance instance = new SerializeInstance();
			 outputStream.writeObject(instance);
			 outputStream.flush();
			 outputStream.close();
			 
		}catch(IOException e) {
			e.printStackTrace();
		}
		
		try {
			//2.The Process of the deSerializing
			FileInputStream fileInputStream = new FileInputStream("D:\\JavaCodes\\Examps\\JasonWord.txt");
			ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
			SerializeInstance instance02 = (SerializeInstance)objectInputStream.readObject();
			System.out.println(instance02.num + "WuLiWaLa");
			
		}catch (IOException | ClassNotFoundException e) {
			 e.printStackTrace();
		}
		System.out.println("Hello World! ");
	}
	
}
补充知识:serialVersionUID是什么用?
这篇博客 的最后部分解释了serialVersionUID的用处和代码验证,
这里做一个简单的总结:serialVersionUID是一个类的序列化版本号, 实现Serializable接口的类,都必须有这个字段(意思是要么手动指定一个,要么在警告的情况下,编译器默认给生成一个,反正得有一个),而且必须是private static final long 数据类型的。有什么用呢?它就像是一把钥匙,只对应某一个对象,反序列化时需要它进行解密。
为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。

显式地定义serialVersionUID有两种用途:
    1、 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
    2、 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。
    



本文在写作过程中,主要参考了以下博客内容,欢迎大家前去参阅:
1.只为成功找方法,不为失败找借口: https://www.cnblogs.com/xdp-gacl/p/3777987.html
2.飞飞飞: https://www.cnblogs.com/gtaxmjld/p/4866931.html

猜你喜欢

转载自blog.csdn.net/qq_37040173/article/details/83896049