🌈个人主页:人不走空
💖系列专栏:算法专题
⏰诗词歌赋:斯是陋室,惟吾德馨
# Java中的序列化和反序列化
在Java中,序列化是将对象的状态写入字节流的机制。它主要用于Hibernate、RMI、JPA、EJB和JMS技术中。
反序列化是序列化的逆操作,即将字节流转换为对象。序列化和反序列化过程是平台无关的,这意味着您可以在一个平台上对对象进行序列化,在另一个平台上进行反序列化。
为了序列化对象,我们调用ObjectOutputStream类的writeObject()方法,而为了反序列化,则调用ObjectInputStream类的readObject()方法。
我们必须实现Serializable接口才能序列化对象。
# Java序列化的优点
它主要用于在网络上传输对象的状态(即称为marshalling)。
java.io.Serializable接口
Serializable是一个标记接口(没有数据成员和方法)。它用于“标记”Java类,以便这些类的对象可以获得某种能力。Cloneable和Remote也是标记接口。
Serializable接口必须由需要持久化其对象的类实现。
String类和所有包装类默认实现了java.io.Serializable接口。
让我们看下面给出的例子:
Student.java
import java.io.Serializable;
public class Student implements Serializable{
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
在上面的示例中,Student类实现Serializable接口。现在它的对象可以转换为流。主类的实现显示在下一个代码中。
专属福利
👉点击领取:Java资料合集!650G!
ObjectOutputStream类
ObjectOutputStream类用于将基本数据类型和Java对象写入OutputStream。只有支持java.io.Serializable接口的对象才能写入流中。
构造函数
重要方法
Method | Description |
1) public final void writeObject(Object obj) throws IOException {} | 它将指定的对象写入 ObjectOutputStream。 |
2) public void flush() throws IOException {} | 它刷新当前输出流。 |
3) public void close() throws IOException {} | 它关闭当前输出流。 |
ObjectInputStream类
ObjectInputStream反序列化使用ObjectOutputStream编写的对象和基本数据。
构造函数
重要方法
Method | Description |
1) public final Object readObject() throws IOException, ClassNotFoundException{} | 它从输入流中读取一个对象。 |
2) public void close() throws IOException {} | 它关闭 ObjectInputStream。. |
# Java序列化的例子
在此示例中,我们将从上面代码的Student类序列化对象。
ObjectOutputStream类的writeObject()方法提供了序列化对象的功能。我们正在将对象的状态保存在名为f.txt的文件中。
Persist.java
import java.io.*;
class Persist{
public static void main(String args[]){
try{
//Creating the object
Student s1 =new Student(211,"ravi");
//Creating stream and writing the object
FileOutputStream fout=new FileOutputStream("f.txt");
ObjectOutputStream out=new ObjectOutputStream(fout);
out.writeObject(s1);
out.flush();
//closing the stream
out.close();
System.out.println("success");
}catch(Exception e){System.out.println(e);}
}
}
输出:
success
# Java反序列化的例子
反序列化是从序列化状态重构对象的过程。它是序列化的逆操作。让我们看一个示例,其中我们从反序列化对象中读取数据。
Deserialization是从序列化状态重构对象的过程。它是序列化的逆操作。让我们看一个示例,其中我们从反序列化对象中读取数据。
Depersist.java
import java.io.*;
class Depersist{
public static void main(String args[]){
try{
//Creating stream to read the object
ObjectInputStream in=new ObjectInputStream(new FileInputStream("f.txt"));
Student s=(Student)in.readObject();
//printing the data of the serialized object
System.out.println(s.id+" "+s.name);
//closing the stream
in.close();
}catch(Exception e){System.out.println(e);}
}
}
输出:
211 ravi
# Java继承(IS-A关系)的序列化
如果一个类实现了Serializable接口,则所有它的子类也将可序列化。让我们看下面给出的例子:
SerializeISA.java
import java.io.Serializable;
class Person implements Serializable{
int id;
String name;
Person(int id, String name) {
this.id = id;
this.name = name;
}
}
class Student extends Person{
String course;
int fee;
public Student(int id, String name, String course, int fee) {
super(id,name);
this.course=course;
this.fee=fee;
}
}
public class SerializeISA
{
public static void main(String args[])
{
try{
//Creating the object
Student s1 =new Student(211,"ravi","Engineering",50000);
//Creating stream and writing the object
FileOutputStream fout=new FileOutputStream("f.txt");
ObjectOutputStream out=new ObjectOutputStream(fout);
out.writeObject(s1);
out.flush();
//closing the stream
out.close();
System.out.println("success");
}catch(Exception e){System.out.println(e);}
try{
//Creating stream to read the object
ObjectInputStream in=new ObjectInputStream(new FileInputStream("f.txt"));
Student s=(Student)in.readObject();
//printing the data of the serialized object
System.out.println(s.id+" "+s.name+" "+s.course+" "+s.fee);
//closing the stream
in.close();
}catch(Exception e){System.out.println(e);}
}
}
输出:
success
211 ravi Engineering 50000
SerializeISA类已序列化扩展了Person类的Student类对象,而Person类是可序列化的。父类属性继承到子类,因此如果父类是可序列化的,则子类也将是可序列化的。
# Java聚合(HAS-A关系)序列化
如果一个类引用另一个类,则所有引用必须是Serializable,否则将不执行序列化过程。在这种情况下,在运行时会抛出NotSerializableException。
Address.java
class Address{
String addressLine,city,state;
public Address(String addressLine, String city, String state) {
this.addressLine=addressLine;
this.city=city;
this.state=state;
}
}
Student.java
import java.io.Serializable;
public class Student implements Serializable{
int id;
String name;
Address address;//HAS-A
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
由于Address不可序列化,因此无法序列化Student类的实例。
注意:对象中的所有对象都必须是可序列化的。
# Java序列化中的静态数据成员
如果一个类中有任何静态数据成员,它将不被序列化,因为静态是类的一部分而不是对象。
Employee.java
class Employee implements Serializable{
int id;
String name;
static String company="SSS IT Pvt Ltd";//it won't be serialized
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
# Java序列化数组或集合
规则:在数组或集合的情况下,数组或集合的所有对象必须是可序列化的。如果任何对象不可序列化,则序列化将失败。
Java中的Externalizable
Externalizable接口提供了以压缩格式将对象状态写入字节流的功能。它不是标记接口。
Externalizable接口提供两个方法:
-
public void writeExternal(ObjectOutput out) throws IOException
-
public void readExternal(ObjectInput in) throws IOException
Java暂时关键字
如果您不想序列化类的任何数据成员,可以将其标记为瞬态。
Employee.java
class Employee implements Serializable{
transient int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
现在,id将不会序列化,因此在序列化之后反序列化对象时,您将不会得到id的值。它始终返回默认值。在这种情况下,它将返回0,因为id的数据类型是整数。
访问下一页获取更多详细信息。
SerialVersionUID
运行时序列化过程将序列化类与每个可序列化类关联一个标识符,称为SerialVersionUID。它用于验证序列化对象的发送方和接收方。发送方和接收方必须相同。为验证它,使用SerialVersionUID。发送方和接收方必须具有相同的SerialVersionUID,否则在反序列化对象时将抛出InvalidClassException。我们还可以在Serializable类中声明自己的SerialVersionUID。
要这样做,您需要创建一个SerialVersionUID字段并为其分配一个值。它必须是长类型,并且带有静态和最终修饰符。建议在类中明确声明serialVersionUID字段,并将其私有化。例如:
private static final long serialVersionUID=1L;
现在,可序列化类将如下所示:
Employee.java
import java.io.Serializable;
class Employee implements Serializable{
private static final long serialVersionUID=1L;
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
}
作者其他作品:
【Java】Spring循环依赖:原因与解决方法
OpenAI Sora来了,视频生成领域的GPT-4时代来了
[Java·算法·简单] LeetCode 14. 最长公共前缀 详细解读
【Java】深入理解Java中的static关键字
[Java·算法·简单] LeetCode 28. 找出字a符串中第一个匹配项的下标 详细解读
了解 Java 中的 AtomicInteger 类
算法题 — 整数转二进制,查找其中1的数量
深入理解MySQL事务特性:保证数据完整性与一致性
Java企业应用软件系统架构演变史