Java Serializable 序列化

Java的Serializable接口是Java序列化机制的核心,它允许一个对象的状态被转换为字节流,从而可以方便地进行存储或传输。
序列化后的对象可以被写到数据库、存储到文件系统,或者通过网络传输。
要在 Java 中使一个类可序列化,你需要让它实现 java.io.Serializable  接口。

一、什么是序列化?

序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。
在Java中,序列化通常指将对象转换为字节流,以便将其保存到文件、发送到另一个系统、或通过网络传输。
反序列化(Deserialization)则是将字节流转换回对应对象的过程。

二、Serializable接口

在Java中,要实现序列化,一个类必须实现java.io.Serializable接口。这个接口是一个“标记接口”,即它不包含任何方法,只是起到一个标记的作用,告诉Java编译器和运行时系统这个类的实例可以被序列化。

三、序列化的基本步骤

‌创建对象‌:首先,你需要有一个你想要序列化的对象。
‌创建输出流‌:然后,你需要创建一个输出流,通常是FileOutputStream,用于将序列化后的字节流写入文件或其他输出设备。
‌创建ObjectOutputStream‌:接下来,你需要创建一个ObjectOutputStream,它将负责将对象转换为字节流并写入输出流。
‌调用writeObject方法‌:使用ObjectOutputStream的writeObject方法将对象序列化并写入输出流。
‌关闭流‌:最后,关闭所有的流以释放资源。
反序列化的步骤类似,只是使用的是FileInputStream和ObjectInputStream,并调用readObject方法来读取和构造对象。

四、注意事项

‌serialVersionUID‌:每个可序列化的类都有一个serialVersionUID,它是一个版本控制的机制,用于验证序列化的对象版本和类定义是否匹配。如果两者不匹配,会抛出InvalidClassException。建议显式地定义这个字段,以避免因版本变化导致的问题。
‌transient关键字‌:如果有些字段不需要序列化,可以使用transient关键字修饰这些字段。被transient修饰的字段在序列化时会被忽略。
‌自定义对象的序列化‌:如果一个对象包含对其他对象的引用,那么这些对象也必须实现Serializable接口。否则,在序列化时会抛出NotSerializableException。
‌处理敏感数据‌:在序列化过程中,注意不要序列化包含敏感信息(如密码、密钥等)的对象。这些信息可能会在序列化后的字节流中暴露。
‌继承关系‌:如果一个类是可序列化的,那么它的所有子类也都是可序列化的,除非子类自己覆盖了序列化行为。
‌安全性‌:反序列化时应该特别小心,不要反序列化来自不信任来源的字节流。这可能会导致安全问题,如代码注入攻击。

五、高级特性

‌自定义序列化‌:通过实现readObject和writeObject方法,你可以自定义对象的序列化和反序列化过程。这在你需要控制序列化格式或处理复杂对象关系时非常有用。
‌替代序列化机制‌:除了Java原生的序列化机制外,还有一些替代的序列化库,如Google的Protocol Buffers、Apache的Thrift、Jackson和Gson等。这些库通常提供了更高效、更灵活的序列化方式,并且可以与多种编程语言互操作。
综上所述,Java的序列化机制是一个强大的工具,允许你方便地将对象的状态持久化或进行网络传输。然而,在使用它时也需要注意一些潜在的问题和限制,以确保序列化的正确性和安全性。

六、示例

要实现序列化,一个类必须实现 java.io.Serializable 接口。这个接口是一个“标记接口”,也就是说,它本身不包含任何方法,只是起到标记作用,告诉Java编译器和运行时环境这个类的实例可以被序列化。

实现Serializable接口

以下是一个简单的例子,展示了如何使一个类实现 Serializable 接口:
import java.io.Serializable;public class Person implements Serializable {private static final long serialVersionUID = 1L;private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}

序列化对象
要将对象序列化到文件中,可以使用 ObjectOutputStream 类:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;public class SerializeDemo {public static void main(String[] args) {Person person = new Person("John Doe", 30);try (FileOutputStream fileOut = new FileOutputStream("person.ser");ObjectOutputStream out = new ObjectOutputStream(fileOut)) {out.writeObject(person);System.out.println("Serialized data is saved in person.ser");} catch (IOException i) {i.printStackTrace();}}
}

反序列化对象
要从文件中反序列化对象,可以使用 ObjectInputStream 类:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class DeserializeDemo {public static void main(String[] args) {Person person = null;try (FileInputStream fileIn = new FileInputStream("person.ser");ObjectInputStream in = new ObjectInputStream(fileIn)) {person = (Person) in.readObject();} catch (IOException i) {i.printStackTrace();} catch (ClassNotFoundException c) {System.out.println("Person class not found");c.printStackTrace();}System.out.println("Deserialized Person: " + person);}
}

注意事项

  • serialVersionUID‌::强烈建议为实现了 Serializable 接口的类添加一个 serialVersionUID 字段。这是一个版本控制的机制,用于验证序列化的对象版本和类定义是否匹配。如果不匹配,会抛出 InvalidClassException。
  • transient‌:如果有些字段不需要序列化,可以使用 transient 关键字修饰这些字段。
  • 处理自定义对象‌:如果一个对象包含对其他对象的引用,那么这些对象也必须实现 Serializable 接口。
  • 安全性‌:序列化可能带来安全问题,因为可以从字节流中构造对象。因此,反序列化时应该特别小心,不要反序列化不信任的数据源的对象。
通过实现 Serializable 接口,你可以方便地将对象的状态持久化或进行网络传输,但也要注意序列化的开销和潜在的安全问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/63299.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS一些小点 —— 12.7

1. box-sizing: border-box box-sizing 属性,默认值为 content-box box-sizing: border-box 使padding和border的值不会再影响元素的宽高;padding和border的值算在指定宽高的内部(但是外边距依然算做外部) 2. overflow: hidden …

【GESP】C++一级练习 luogu-P1425, 小鱼的游泳时间

GESP一级综合练习,主要涉及时间计算,难度★☆☆☆☆。 题目题解详见:https://www.coderli.com/gesp-1-luogu-p1425/ 【GESP】C一级练习 luogu-P1425, 小鱼的游泳时间 | OneCoderGESP一级综合练习,主要涉及时间计算,难…

【网络协议栈】数据链路层(内附手画分析图 简单易懂)以太网、MAC地址、局域网、交换机、MTU、ARP协议

每日激励:【无限进步】“梦想可以大,但第一步总是小” 绪论​: 本章将开始到达TCP/IP协议中的最后一层数据链路层,本章将会写到我们日常中常见的局域网以及认识数据链路层中非常重要的协议ARP协议,后续还将进行更新网络…

docker怎么commit tag push?

在 Docker 中,commit、tag 和 push 是用于创建和推送自定义镜像到仓库的三个不同步骤。以下是每个命令的详细说明和使用方法: ### 1. docker commit 当你对一个运行中的容器做了修改,并希望将这些修改保存为一个新的镜像时,可以使…

Java多线程与线程池技术详解(四)

接受失败:“失败是什么?没有什么,只是更走近成功一步;成功是什么?就是走过了所有通向失败的路,只剩下一条路,那就是成功的路。”这句话很好地诠释了如何看待失败的问题,即每一次跌倒…

二叉树的深搜(不定期更新。。。。。)

二叉树的深搜 验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左 子树 只包含 小于 当前节点的数。 节点的右子树只包含 大于 当前节点的数。 所有左子树和右子树自身必须也是二叉…

51c嵌入式~单片机合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/12581900 一、STM32代码远程升级之IAP编程 IAP是什么 有时项目上需要远程升级单片机程序,此时需要接触到IAP编程。 IAP即为In Application Programming,解释为在应用中编程,用户自己的程…

使用setsockopt函数SO_BINDTODEVICE异常,Protocol not available

前言 最近在使用OLT的DHCP Server的时候发现一些异常现象,就是ONU发的一个vlan的discover包其他不同vlan的DHCP地址池也会收到,导致其他服务器也发了offer包,ONU同时会有多个ip地址。一开始是没有使用SO_BINDTODEVICE,后面查到使…

02 conda常用指令

目录 命令快速查找命令详细解释列出当前conda中存在的解释器环境使用指定的解释器环境创建虚拟环境激活自己创建的虚拟环境虚拟环境删除切换回主环境找到你计算机中安装的miniconda3的跟目录找到虚拟环境的目录选择需要删除的虚拟环境文件夹确认环境是否删除 补充删除虚拟环境指…

BEVFormer详细复现方案

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

应用案例 | 船舶海洋: 水下无人航行器数字样机功能模型构建

水下无人航行器数字样机功能模型构建 一、项目背景 为响应水下装备系统研制数字化转型及装备系统数字样机建设的需要,以某型号水下无人航行器(Underwater Unmanned Vehicle,UUV)为例,构建UUV数字样机1.0功能模型。针对…

npm (Node Package Manager) 简介

npm 是 Node.js 的默认包管理工具,用于管理和分发JavaScript库和工具。它允许开发者轻松安装、更新、配置和卸载这些包。npm 提供了一个命令行客户端,同时也维护着一个大型的在线软件注册表(npm registry),其中包含了成…

【NIPS2024】Unique3D:从单张图像高效生成高质量的3D网格

背景(现有方法的不足): 基于Score Distillation Sampling (SDS)的方法:从大型二维扩散模型中提取3D知识,生成多样化的3D结果,但存在每个案例长时间优化问题/不一致问题。 目前通过微…

手机LCD分区刷新技术介绍

分区刷新也称为分区变频,LCD分区刷新功能的目的是将屏幕分为上下半区,分区显示不同帧率,上方区块High Frame Rate,下方区块Low Frame Rate。使用者可以动态自定义上方高刷显示区的结尾位置。 当前的智能手机屏幕上,显示…

NLP算法具备技能

摘要:好久不看理论,最近把自己学过以及用到过的东西都列了出来,主要是这个大纲体系,详细的内容部分是使用LLM来辅助编写的。 一、大模型 1.1 常用大模型 1.1.1 Qwen ‌Qwen大模型‌是由阿里巴巴开发的系列大语言模型&#xff…

学习日志022 -- python事件机制

作业: 1】思维导图 2】完成闹钟 main.py import sysfrom PySide6.QtCore import QTimerEvent, QTime,Qt from PySide6.QtGui import QMovie,QMouseEvent from PySide6.QtWidgets import QApplication, QWidget from Form import Ui_Formclass MyWidget(Ui_Form,Q…

服务器被ping的风险,如何开启和禁止ping?

允许服务器被ping(即响应ICMP回显请求)有其风险和好处。允许ping的主要好处是它可以帮助网络管理员快速检查服务器的连通性。然而,这也可能带来一些安全风险,例如: 暴露信息:响应ping请求可以让攻击者知道…

JAVAWeb中的Servlet学习

一 Servlet简介 1.1动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源.例如:html css js img ,音频文件和视频文件 动态资源 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如Servle…

重生在我在21世纪学C++—赋值操作符、类型转换、单目操作符

一、赋值操作符 在变量创建的时候给一个初始值叫初始化。在变量创建好后,再给⼀个值,这叫赋值。 int a 100 ; //这叫初始化 a 200 ; //这叫赋值, 就是赋值操作符 赋值操作符 是⼀个随时可以给变量(不能是常…

03、Node.js安装及环境配置

1.下载node.js 下载地址:Node.js 2.安装 2.1 自定义安装路径(可以选择默认) 下图根据本身的需要进行,我选择了默认Node.js runtime,然后Next: Node.js runtime :表示运行环境 npm package mana…