一、序列化:将Java对象转换成字节流的过程
- 序列化过程:是指把一个Java对象变成二进制内容,实质上就是byte[]。因为序列化后可以把byte[]保存到文件中,或者把byte[]通过网络传输到远程(IO),如此就相当于把java存储到文件或者通过网络传输出去了
二、反序列化:将字节流转换成Java对象的过程
- 反序列化过程:把一个二进制内容(也就是byte[])变回Java对象。有了反序列化,保存到文件中的byte[]又可以“变成”java对象,或者从网络上读取byte[]并把它“变成”Java对象。
三、为什么需要序列化
当两个进程进行远程通信时,可以互相发送各种类型的数据(包括文本、图片、音频、视频等),而这些数据都会以二进制序列的形式在网络上传送。当两个Java进程进行通信时,需要Java序列化和反序列化实现进程间的对象传送,换句话说,一方面,发送方需要把这个 Java 对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出 Java 对象。
作用:
-
实现了数据的持久化,序列化可以把数据永久地保存在硬盘上(通常存放在文件里)
-
通过序列化以字节流的形式使对象在网络中进行传递和接收
-
通过序列化在进程间传递对象
注意事项:
1、某个类可以被序列化,则其子类也可以被序列化。
2、声明为static和transient的成员变量,不能被序列化。static成员变量是描述类级别的属性,transient表示临时数据
3、一个 Java 对象要能序列化,必须实现java.io.Serializable接口。因为序列化是一个非常复杂的算法操作,所以java官方给我们写好了,但是使用的方式很特殊,java底层写好了序列化操作,但是官方并不确定”你的Java对象”是否需要序列化,因此官方搞了一个”接口标记”的操作。如果对象需要底层的序列化操作,就实现Serializable 接口,如果对象不需要底层的序列化操作,就不需要实现Serializable 接口
Serializable 接口源码:
public interface Serializable { }
Serializable 没有定义任何方法,它是一个空接口。这样的空接口称为“标记接口”(Marker Interface),其存在的意义就是为了添加标记
四、序列化方式
默认情况下,JVM负责编写和读取可序列化对象的过程,序列化/反序列化功能通过对象流类的以下两种方法公开
- ObjectOutputStream.writeObject(object):将可序列化的对象写入输出流
- ObjectInputStream.readObject():从输入流读取,构造并返回一个对象
package com.chenly.serialize; import com.chenly.serialize.bean.Score; import java.io.*; /** * @author: chenly * @date: 2022-11-25 17:14 * @description: * @version: 1.0 */ public class Test { public static void main(String[] args) { Score score1 = Score.builder() .className("一班") .stuName("张三").course("生物").score(90).build(); Test test = new Test(); //序列化 byte[] bytes= test.serialize(score1); //反序列化 Object object = test.deserialize(bytes); System.out.println("反序列化输出:"+object); } private byte[] serialize(Object object) { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream=null; try { objectOutputStream = new ObjectOutputStream(out); //序列化 objectOutputStream.writeObject(object); return out.toByteArray(); } catch (IOException e) { e.printStackTrace(); return null; } } private Object deserialize(byte[] bytes) { InputStream in = new ByteArrayInputStream(bytes); ObjectInputStream objectInputStream=null; try { objectInputStream = new ObjectInputStream(in); //反序列化 Object object=objectInputStream.readObject(); return object; } catch (Exception e) { e.printStackTrace(); return null; } } }
五、serialVersionUID常数
- serialVersionUID是一个常数,用于标识可序列化类的版本,JVM在反序列化过程中检查此常数,如果正在反序列化的对象的serialVersionUID与类中指定的序列号不同,则JVM抛出InvalidClassException。
- serialVersionUID 是可选的,如果不显式声明,Java编译器将自动生成一个,自动生成的serialVersionUID 是基于类的元素(成员变量、方法和构造函数等)计算的。如果这些元素一旦发生更改,serialVersionUID 也将更改。
例如:定义了一个Student类,未显示声明serialVersionUID ,序列化后保存到文件中,之后在Student类中新增一个字段address,此时将文件中的Student对象反序列化就会抛异常,无法反序列化回来了。如果定义了serialVersionUID ,即使在Student里加了一个属性,但还是可以反序列化回来的,只是新加的那个属性值为null而已
标签:Java,对象,object,byte,序列化,serialVersionUID From: https://www.cnblogs.com/kiko2014551511/p/16932750.html