Java序列化接口,为什么提倡所有类都实现?
创始人
2025-07-01 08:01:15
0

什么是序列化和反序列化?

Java提供了一种对象序列化的机制。

序列化:把java对象转换为字节序列的过程;在网络传输对象或者将对象持久化到文件中时,将对象转换成有序字节流,字节流中包含对象完整的状态数据信息,保证对象的完整性和可传递性。

反序列化:把字节序列转换为java对象的过程;程序在文件或者网络传输中,获取到字节流后,根据字节流中包含的对象状态数据信息,重建java对象的过程。

可以将序列化想象成人去银行存钱的过程。

将现金放入ATM机中,存入银行卡中的过程可当作序列化的过程。

现金 => ATM => 银行卡   
java对象  => JVM => 字节序列

将银行卡中的钱通过ATM取出的过程,可以当作反序列化的过程。

银行卡 => ATM => 现金 
字节序列  => JVM => java对象

为什么要序列化?

在文件存储和网络传输时,所有的文件,视频也好,文本,图片,音频也好,都是以二进制序列的形式进行存储或传输。

那么在java两个进程中进行通信的时候,就需要我们也同样利用二进制进行传输,而往往客户端在接收到服务端传输过来的字节序列后,由jvm将字节序列转换为java对象,已供程序使用。

由于序列化是jvm提供的一种机制,所有序列化可以保证在一个平台中序列化后的对象,可以在另一个平台上进行重建出来

Java如何实现序列化和反序列化?

JDK序列化接口

java.io.ObjectOutputStream:表示对象输出流。

try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.txt"))){
    objectOutputStream.writeObject(userOut);
}

初始化一个指向user.text文件的输出流。

objectOutputStream.writeObject(userOut);方法可以将对象二进制输出到指向的user.text中。

java.io.ObjectInputStream:表示对象输入流。

try(ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("user.txt"))) {
   User user = (User) objectInputStream.readObject();
}

初始化一个指向uset.text文件的输入流。

objectInputStream.readObject();方法可以将文件user.text中的字节序列读取并重建对象,重建后可直接强制转换为序列化前的对象。

实例化对象的要求

只有自身类或者父类、实现类实现了Serializable接口的类对象才能被序列化,否则抛出java.io.NotSerializableException异常,需要注意的是,如果类的成员变量属于类对象,那么也需要实现Serializable接口才能实例化,否则也将抛出异常。

若实现了Serializable接口,在序列化时,将递归将对象的属性(方法不会序列化)转化为字节序列:

ObjectOutputStream采用默认的序列化方式,对User对象的非transient的实例变量进行序列化。

ObjcetInputStream采用默认的反序列化方式,对User对象的非transient的实例变量进行反序列化。

序列化和反序列化代码实例:

import java.io.*;

public class TestSerializable {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User userOut = new User("榴莲java", 23,"a");
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.txt"))){
            objectOutputStream.writeObject(userOut);
        }

        try(ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("user.txt"))) {
            User userPut = (User) objectInputStream.readObject();
            System.out.println(userPut.toString());
        }

    }

    static class User implements Serializable {
        private static final long serialVersionUid = 9992L;
        private transient String name;
        private Integer age;
        public User(String name, Integer age, String sex) {
            this.name = name;
            this.age = age;
        }
        public String toString(){
            return "name:" + this.name + "\tage:" + this.age;
        }
    }
}

执行结果:

name:null age:23

transient关键字详解

大家也看到了,上述代码执行结果中name变量并未实例化,原因是name被transient关键字修饰,用transient关键字标记的成员变量将不参与类的实例化和反实例化过程。

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...