JDK自带的序列化
核心特点
-
简洁性:JDK的序列化机制极其简便,仅需目标类实现Serializable接口即可,该接口作为标记接口,不强制要求实现任何方法,仅用于指示该类支持序列化。
-
版本控制:每个可序列化的类都隐式或显式地拥有一个serialVersionUID,用以在反序列化时确保类版本的一致性。若未显式指定,编译器将自动生成此ID。
优点
-
易用性:实现序列化仅需一行代码(实现接口),极大降低了开发门槛。
-
数据完整性:由于JDK序列化机制会将对象的类描述、属性元数据及继承关系等信息一并序列化,确保了数据的完整性和恢复时的准确性。
缺点
-
跨语言局限性:作为JDK的一部分,其序列化格式高度依赖Java语言,因此不支持跨语言间的无缝传输与反序列化。
-
性能开销:由于序列化过程中包含了大量的元数据,导致生成的二进制流体积较大,增加了网络传输或文件存储的负担,降低了性能。
-
安全风险:序列化数据中包含了类的详细信息,若未妥善处理,易受到反序列化攻击,攻击者可能构造恶意数据以实例化非预期对象,造成系统安全漏洞。
实例代码:
实体对象:Request
- 实体对象必要要继承Serializable接口,如果某个属性不需要序列化只需要添加transient修饰符或者static,代表当前属性不属于序列化,既是反序列化也不会得到当前这个属性的值
package com.zhz.test.serialization.jdk;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serial;
import java.io.Serializable;/*** @author zhouhengzhe*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Request implements Serializable {@Serialprivate static final long serialVersionUID = -938293548547683122L;private String id;private String url;private String method;private String requestBody;private String requestHeader;private String requestParam;private String requestCookie;
}
测试序列化&反序列化的代码:
@Test@SneakyThrowspublic void testJdkSerialization() {Request request = Request.builder().id("1").url("http://www.baidu.com").method("GET").requestBody("requestBody").requestHeader("requestHeader").requestParam("requestParam").requestCookie("requestCookie").build();//序列化成二进制流System.out.println("序列化 init-------------------");FileOutputStream fileOutputStream = new FileOutputStream("D:\ideaproject\test\src\test\java\com\zhz\test\serialization\jdk\request.txt");ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);objectOutputStream.writeObject(request);objectOutputStream.close();fileOutputStream.close();System.out.println("序列化 final-------------------");//反序列化为Java对象System.out.println("反序列化 init-------------------");//当前文件路径为生成后的序列化的文件的路径FileInputStream fileInputStream = new FileInputStream("D:\ideaproject\test\src\test\java\com\zhz\test\serialization\jdk\request.txt");ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);Request readRequest = (Request) objectInputStream.readObject();System.out.println(readRequest);System.out.println("反序列化 final-------------------");}
-
序列化:
- ObjectOutputStream 接收一个实现了 OutputStream 接口的流作为参数,该流指定了序列化后对象数据的输出目标(如文件、网络套接字等)。通过灵活地选择不同类型的 OutputStream 实现(如 FileOutputStream 用于文件写入,ByteArrayOutputStream 用于内存中的字节流),可以方便地将序列化后的对象数据保存到所需的位置。
-
反序列化
- ObjectInputStream 与 FileInputStream 结合使用,将之前序列化到文件中的对象数据读取回来,并重新构造为Java中的对象实例。这个过程允许程序从持久化存储(如文件系统)中恢复对象状态,以便进一步使用。