Java中的可序列化接口与示例
已发表: 2021-11-29Java 提供了几个包,Serializable 接口就是其中之一。 它存在于 Java 包 java.io 中,是一种标记接口。 当定义为标记接口时,接口中不存在任何方法或字段。 因此,每当任何类实现接口时,接口都不需要实现任何方法。 如果类希望它们的实例被序列化或反序列化,则这些类实现接口。
序列化机制用于将对象状态转换为字节流。 该机制是通过使用 ObjectOutputStream 来实现的。 反序列化的过程与序列化的过程正好相反。 在这种情况下,字节流被转换回 Java 的对象。 ObjectInputStream 用于反序列化。
目录
序列化
将任何对象的状态转换为字节流称为序列化。 而序列化的反面是反序列化。 Java 的对象可以转换为静态字节流。 然后可以将此静态流保存在数据库中,或者也可以将其传输到不同的网络。 序列化的过程是实例相关的。 这意味着对象的序列化可以在一个平台上进行,然后对象的反序列化可以在另一个平台上进行。 为序列化过程实现了一种特定类型的标记接口“Serializable”。 因此,符合序列化条件的类,即Java 中的可序列化类,应该实现标记接口。
这种将对象状态写入字节流的机制称为序列化。 该机制主要用于 JMS、EJB、JPA、RMI 和 Hibernate 技术。
ObjectInputStream 和 ObjectOutputStream 是扩展 java.io.InputStream 和 java.io.OutputStream 的高级类的形式。 原始类型和对象图可以由 ObjectOutputStream 以字节形式写入 OutputStream
溪流。 转换产生的流可以通过 ObjectInputStream 读取。 因此,对于序列化,方法 writeObject() 从 ObjectOutputStream 调用,对于反序列化,方法 readObject() 从 ObjectInputStream 类调用。
ObjectOutputStream中最重要的方法是:
上面这行代码取自 https://www.baeldung.com/java-serialization。
在上面的代码行中,取了一个可序列化的对象,然后将其转换为流或字节流。
在 ObjectInputStream 的情况下,最关键的方法是:
上面这行代码取自 https://www.baeldung.com/java-serialization。
上面这行代码可以读取字节序列并将这个字节流转换为Java的对象。 原来的对象可以通过这个回退。
序列化过程的图示可以描述如下:
考虑将“Person”类进行序列化。 静态字段没有序列化,它们属于某些类。 在序列化过程中使用关键字“transient”可以忽略类字段。
资源
可以将 person 类型的对象保存到某个本地文件中,然后将值读回。下面显示的代码可以用于此目的。
ObjectOutputStream 用于通过使用 FileOutputStream 将对象状态保存到文件中。 在此示例中,已在项目目录中创建了一个名为“yourfile.txt”的文件。 通过使用 FileInputStream,加载创建的文件。 然后这个流被 ObjectInputStream 拾取并转换成一个名为 p2 的新对象。 最后测试加载的对象的状态,并与原始对象的状态匹配。 加载的对象必须明确地投射给典型的人。
Java 序列化的注意事项
一、继承与组合
每当用户实现接口 java.io.Serializable 时,所有实现该接口的类子类都变为可序列化的。 此外,如果一个对象持有对不同对象的引用,则引用来实现接口的对象是可单独序列化的; 如果这些对象没有实现接口,则会抛出异常。 抛出的异常将是 NotSerializableException。 此外,如果假设对象数组存储在可序列化对象中,则所有数组对象都应序列化。 如果没有发生对象的序列化,那么它将抛出异常“NotSerializableException”。
2.序列版UID
对于实现 Serializable 接口的每个类,每个类都关联一个数字。 该编号与 Java 虚拟机相关联。 这主要是为了验证加载和保存的对象是否具有确切的属性。 只有当属性相同时,对象才会在序列化时兼容。 IDE 会自动生成这些数字,并且主要基于类的名称、其属性以及与之关联的访问修饰符。 如果更改导致不同的数字,则会引发异常“InvalidClassException”。
如果可序列化类未声明 serialVersionUID,JVM 将在运行时自动生成它。 虽然会自动生成数字,但仍然建议类声明一个 serialVersionUID。 这是因为将自动生成的 serialVersionUID 将依赖于编译器,并且有时可能会抛出意外的 InvalidClassExceptions。
3.自定义序列化
在 Java 中设置了一种默认方式来序列化对象。 Java 可以覆盖此默认行为。 有一种自定义序列化的方法。 在尝试序列化具有不可序列化属性的对象的情况下,它特别有用。 此类对象的序列化可以通过用户想要序列化的类中的两种方法来完成。 这两种方法是:
上面两种方法都可以用来将属性序列化成任何可以序列化的形式,之前是不可序列化的。
Java中序列化的优点
Java 中序列化的优点之一是对象的状态可以在网络上传播。
Java 接口 java.io.Serializable
java.io.Serializable 是一个标记接口,这意味着接口中没有方法和对象。 标记界面的主要功能是标记
Java 的类赋予类的所有对象特定的能力。 标记接口的示例是 Remote 和 Cloneable。
该接口必须由使用该接口序列化其对象的任何类实现。 默认情况下,包装类和String类等类实现了接口java.io.Serializable。
下面显示了一个 java 可序列化的示例。
在上面的代码中,可以观察到Student类实现了Serializable接口。 因此一旦类实现了 Serializable 接口,类中的对象就可以转换为字节流。
ObjectOutputStream 类
此类用于将原始类型的数据和 Java 对象写入 OutputStream。 支持接口 java.io.Serializable 的对象可用于写入流。
ObjectInputStream 类
通过使用 ObjectOutputStream 写入的所有原始数据都使用 ObjectInputStream 进行反序列化。
Java 中的 Serializable 接口示例如下所示。
在本例中,Student 类将被序列化。 ObjectOutputStream 类的 writeObject() 方法提供了序列化对象的所有功能。 对象的状态保存在名为 f.txt 的文件中。
结论
本文讨论了 Java 中的序列化概念。 它列出了序列化类对象所需的接口和其他重要方法。 序列化过程总是与每个可序列化类的 id 或数字相关联。 此数字称为 SerialVersionUID。 SerialVersionUID 的主要用途是验证要序列化的对象的发送方和接收方。 这是因为发送者和接收者都应该是相同的。
它是 Java 编程语言的一个重要特性。 如果您想进一步了解 Java 中这些重要的特性和概念并掌握您的编程语言技能,您可以查看 upGrad 提供的软件工程课程。 如果您是在职专业人士,该课程最适合您。 对于任何形式的查询,可以联系我们的协助团队。 您也可以浏览我们的网站了解具体课程并获取详细信息。 Serializable 接口是一个标记接口。 标记接口向 Java 运行时提供了一个提示,即实现类允许自己被序列化。 运行时将利用此接口序列化对象。 java中的可序列化接口是java中数据类实现的一种特殊接口。 当一个类实现了这个接口时,它可以被持久化在数据库中。 该接口在 java.io 包中声明。 Serializable 接口有两个方法, readResolve() 和 writeReplace() ,用于读取和写入数据库中的对象。 在Java中实现Serializable接口意味着拥有一个可以在任何具有Serializable接口的系统中序列化和反序列化的对象。 当类被第三方库(JSON、XML 等)或网络协议从外部序列化时,此类接口的实现将是有效的。 当一个变量被声明为 Serializable 时,如果变量的每个实例作为参数传递给方法或从方法返回时,它将被序列化和反序列化。 序列化以编程方式执行,以便可以保留对象的状态以供以后需要反序列化并呈现给对象的用户时使用。 序列化对象是包含字节流的对象。 对象的构造函数或 writeObject() / readObject() 方法用于将字节流放入对象中。 存储的数据可以是文本、音频、视频或任何自定义应用程序数据。 这些对象的数据可以存储在文件中或远程服务器上。 要通过网络传输序列化对象,必须使用 RMI(远程方法调用)协议。 RMI 是用于创建分布式应用程序的良好协议。 它使客户端能够与在服务器上运行的 Java 应用程序中的对象上的方法进行通信。 RMI 协议是一种远程过程调用 (RPC) 机制。 Java中的可序列化接口是什么?
如果我们在 Java 中实现 Serializable 接口会发生什么?
我们可以通过网络传输序列化对象吗?