Java 的对象序列化与反序列化

devtools/2025/1/23 7:55:23/

目录

一、什么是对象序列化与反序列化

二、为何需要对象序列化与反序列化

三、Java 中如何实现对象序列化与反序列化

1. 简单对象的序列化与反序列化

2. 处理静态成员与瞬态成员

四、自定义序列化与反序列化逻辑

五、对象序列化与反序列化的注意事项

六、总结


 

在 Java 开发中,对象序列化与反序列化是一项强大且实用的技术,它就像一座桥梁,连接着内存中的对象世界与外部存储媒介。通过这一技术,我们能将对象的状态保存下来,方便后续恢复与使用,这在数据持久化、网络传输等场景中发挥着不可或缺的作用。接下来,让我们一同深入探究这一技术的奥秘。

一、什么是对象序列化与反序列化

简单来说,对象序列化是将 Java 对象转换为字节流的过程,以便将其存储到文件、数据库或通过网络传输。而反序列化则是相反的操作,将字节流重新转换回 Java 对象,恢复其在内存中的状态。

想象你有一个精美的乐高模型,要暂时收起来或者送给远方的朋友。序列化就像是把这个模型拆分成一个个小块,打包成便于运输的包裹;反序列化则是收到包裹后,按照说明重新把这些小块组装成原来的乐高模型。在 Java 里,对象就如同乐高模型,字节流是包裹,通过序列化和反序列化,对象能在不同环境中实现存储与还原。

二、为何需要对象序列化与反序列化

  1. 数据持久化:程序运行过程中产生的对象数据,需要长期保存下来。比如游戏中的角色数据,玩家退出游戏后,将角色的等级、装备等信息通过序列化存入文件,下次玩家登录时,再通过反序列化恢复这些数据,让角色能以之前的状态继续游戏。
  2. 网络传输:在分布式系统中,不同节点间常需传递对象信息。例如,一个电商系统的订单处理模块,需将订单对象从订单生成节点传输到支付节点,对象序列化能让订单对象以字节流形式在网络中传输,到达目标节点后再反序列化还原。

三、Java 中如何实现对象序列化与反序列化

在 Java 中,实现对象序列化与反序列化,需依赖java.io.Serializable接口。只要一个类实现了该接口,它的对象就能被序列化。

1. 简单对象的序列化与反序列化

java">import java.io.*;class User implements Serializable {private String name;private int age;public User(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}
}public class SerializationExample {public static void main(String[] args) {User user = new User("Alice", 30);String filePath = "user.ser";// 序列化try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath))) {oos.writeObject(user);System.out.println("对象已成功序列化到文件:" + filePath);} catch (IOException e) {e.printStackTrace();}// 反序列化try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {User deserializedUser = (User) ois.readObject();System.out.println("反序列化后的用户信息:姓名 - " + deserializedUser.getName() + ",年龄 - " + deserializedUser.getAge());} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

上述代码中,User类实现了Serializable接口。在main方法中,先创建一个User对象,然后通过ObjectOutputStream将其序列化到文件user.ser中。接着,使用ObjectInputStream从文件中读取字节流,反序列化恢复出User对象,并打印其信息。

2. 处理静态成员与瞬态成员

静态成员属于类,而非对象实例,所以不会被序列化。瞬态(transient)成员也不会被序列化,常用于保护敏感信息。

java">import java.io.*;class Employee implements Serializable {private String name;private transient int salary;private static String company = "ABC Corp";public Employee(String name, int salary) {this.name = name;this.salary = salary;}public String getName() {return name;}public int getSalary() {return salary;}public static String getCompany() {return company;}
}public class TransientExample {public static void main(String[] args) {Employee employee = new Employee("Bob", 5000);String filePath = "employee.ser";// 序列化try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath))) {oos.writeObject(employee);System.out.println("对象已成功序列化到文件:" + filePath);} catch (IOException e) {e.printStackTrace();}// 反序列化try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {Employee deserializedEmployee = (Employee) ois.readObject();System.out.println("反序列化后的员工信息:姓名 - " + deserializedEmployee.getName());// 这里salary为默认值0,因为被transient修饰System.out.println("工资 - " + deserializedEmployee.getSalary());System.out.println("公司 - " + Employee.getCompany());} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

Employee类中,salary被声明为transientcompany是静态成员。反序列化后,salary变为默认值 0,而company的值保持不变,因为静态成员不参与序列化。

四、自定义序列化与反序列化逻辑

有时,默认的序列化与反序列化方式无法满足需求,可通过实现writeObjectreadObject方法自定义逻辑。

java">import java.io.*;class Product implements Serializable {private String name;private double price;public Product(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public double getPrice() {return price;}// 自定义序列化逻辑private void writeObject(ObjectOutputStream oos) throws IOException {oos.writeUTF(name);// 对价格进行加密处理后再写入double encryptedPrice = price * 1.1;oos.writeDouble(encryptedPrice);}// 自定义反序列化逻辑private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {name = ois.readUTF();// 读取后解密价格double encryptedPrice = ois.readDouble();price = encryptedPrice / 1.1;}
}public class CustomSerializationExample {public static void main(String[] args) {Product product = new Product("Laptop", 1000.0);String filePath = "product.ser";// 序列化try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath))) {oos.writeObject(product);System.out.println("对象已成功序列化到文件:" + filePath);} catch (IOException e) {e.printStackTrace();}// 反序列化try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {Product deserializedProduct = (Product) ois.readObject();System.out.println("反序列化后的产品信息:名称 - " + deserializedProduct.getName() + ",价格 - " + deserializedProduct.getPrice());} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

Product类中,通过自定义writeObjectreadObject方法,对price进行加密写入与解密读取,实现了特殊的序列化与反序列化逻辑。

五、对象序列化与反序列化的注意事项

  1. 版本兼容性:若类结构发生变化,可能导致反序列化失败。可通过在类中定义serialVersionUID字段,确保版本兼容性。只要serialVersionUID不变,即使类结构有小变动,仍能成功反序列化。
  2. 安全问题:反序列化未经验证的数据可能导致安全漏洞,如远程代码执行攻击。务必确保反序列化的数据源可靠,或对输入数据进行严格校验。

六、总结

对象序列化与反序列化是 Java 编程中的重要技术,为数据持久化和网络传输提供了便利。通过实现Serializable接口,我们能轻松完成对象的序列化与反序列化操作。必要时,还可自定义逻辑,满足特殊需求。但在使用过程中,要注意版本兼容性和安全问题。掌握这一技术,能极大提升 Java 应用的数据处理能力。希望大家在今后的开发中,能灵活运用对象序列化与反序列化,让程序更加健壮和高效。要是遇到问题,欢迎随时交流,一起在 Java 编程的路上不断进步。


http://www.ppmy.cn/devtools/152824.html

相关文章

人形机器人将制造iPhone!

前言 优必选机器人和富士康通过一项突破性的合作伙伴关系,正在将先进的人形机器人(如Walker S1及其升级版Walker S2)整合到制造流程中,以改变iPhone的生产方式。这一合作旨在通过提升机器人能力、优化工作流程以及实现更智能的自动…

Elasticsearch 8.17.1 JAVA工具类

一、ElasticSearchUtils package com.wssnail.elasticsearch.util;import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._types.FieldValue; import co.elastic.clients.elasticsearch._types.Refresh; import co.elasti…

cf<contest/1971>练习-python版

https://codeforces.com/contest/1971 前5题python题解(cf翻译代码符号可能变中文) 1.My First Sorting Problem 题面翻译 有 t t t 组数据,每组数据给你两个整数 x x x 和 y y y 。 输出两个整数: x x x 和 y y y 中较小…

【前端动效】HTML + CSS 实现打字机效果

目录 1. 效果展示 2. 思路分析 2.1 难点 2.2 实现思路 3. 代码实现 3.1 html部分 3.2 css部分 3.3 完整代码 4. 总结 1. 效果展示 如图所示,这次带来的是一个有趣的“擦除”效果,也可以叫做打字机效果,其中一段文本从左到右逐渐从…

Azure面试

文章目录 项目地址一、Azure Storage1. What are the benefits of Azure Storage? 二、汇总 项目地址 教程作者:教程地址: 代码仓库地址: 所用到的框架和插件: dbt airflow一、Azure Storage 1. What are the bene…

窗口栏组件

在Qt中,窗口的布局可以由多个常用的部件组成。你提供的代码涉及了菜单栏、工具栏、状态栏、中心部件和铆接部件(即停靠窗口)。下面是每个部件的详细解析: 1. 菜单栏 (QMenuBar) Qt中的菜单栏用来创建应用程序的顶部菜单&#xf…

高水平EI会议-第四届机器学习、云计算与智能挖掘国际会议

一、会议信息 大会名称:第四届机器学习、云计算与智能挖掘国际会议(MLCCIM 2025) 会议地点:中国漠河 会议时间:2025年7月21-25日 截稿日期:2025年5月10日 支持单位:佛山市人工智能学会、佛…

关于噪声抑制的一份介绍

在数字图像处理中,噪声问题是时常发生的,在这篇文章中将介绍有关噪声抑制的内容,具体包括有关噪声的介绍、抑制的算法等。 一、噪声 首先,我们知道图像噪声是指在拍摄或传输时图像所受到的随机干扰。而常见的噪声一般有两种&…