前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java】Java序列化和反序列化

【Java】Java序列化和反序列化

作者头像
人不走空
发布2024-06-28 09:18:16
970
发布2024-06-28 09:18:16
举报
文章被收录于专栏:学习与分享学习与分享

# 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

代码语言:javascript
复制
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接口。现在它的对象可以转换为流。主类的实现显示在下一个代码中。

代码语言:javascript
复制

专属福利

👉点击领取: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

代码语言:javascript
复制
代码语言:javascript
复制
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);}     }    }    

输出:

代码语言:javascript
复制
代码语言:javascript
复制
success

# Java反序列化的例子

反序列化是从序列化状态重构对象的过程。它是序列化的逆操作。让我们看一个示例,其中我们从反序列化对象中读取数据。

Deserialization是从序列化状态重构对象的过程。它是序列化的逆操作。让我们看一个示例,其中我们从反序列化对象中读取数据。

Depersist.java

代码语言:javascript
复制
代码语言:javascript
复制
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);}   }  }  

输出:

代码语言:javascript
复制
代码语言:javascript
复制
211 ravi

# Java继承(IS-A关系)的序列化

如果一个类实现了Serializable接口,则所有它的子类也将可序列化。让我们看下面给出的例子:

SerializeISA.java

代码语言:javascript
复制
代码语言:javascript
复制
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);}     }    }  

输出:

代码语言:javascript
复制
代码语言:javascript
复制
success211 ravi Engineering 50000

SerializeISA类已序列化扩展了Person类的Student类对象,而Person类是可序列化的。父类属性继承到子类,因此如果父类是可序列化的,则子类也将是可序列化的。

# Java聚合(HAS-A关系)序列化

如果一个类引用另一个类,则所有引用必须是Serializable,否则将不执行序列化过程。在这种情况下,在运行时会抛出NotSerializableException。

Address.java

代码语言:javascript
复制
代码语言:javascript
复制
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

代码语言:javascript
复制
代码语言:javascript
复制
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

代码语言:javascript
复制
代码语言:javascript
复制
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

代码语言:javascript
复制
代码语言:javascript
复制
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字段,并将其私有化。例如:

代码语言:javascript
复制
代码语言:javascript
复制
private static final long serialVersionUID=1L;  

现在,可序列化类将如下所示:

Employee.java

代码语言:javascript
复制
代码语言:javascript
复制
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;     }    }    
代码语言:javascript
复制

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # Java序列化的优点
  • java.io.Serializable接口
  • 专属福利
  • ObjectOutputStream类
  • ObjectInputStream类
  • # Java序列化的例子
  • # Java反序列化的例子
  • # Java继承(IS-A关系)的序列化
  • # Java聚合(HAS-A关系)序列化
  • # Java序列化中的静态数据成员
  • # Java序列化数组或集合
  • Java中的Externalizable
  • Java暂时关键字
  • SerialVersionUID
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档