文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java序列化和反序列化(详解)

2023-09-11 20:09

关注

Serialization(序列化)将java对象以一连串的字节保存在磁盘文件中的过程,也可以说是保存java对象状态的过程。序列化可以将数据永久保存在磁盘上(通常保存在文件中)。

deserialization(反序列化)将保存在磁盘文件中的java字节码重新转换成java对象称为反序列化。

两个进程在远程通信时,可以发送多种数据,包括文本、图片、音频、视频等,这些数据都是以二进制序列的形式在网络上传输。

java是面向对象的开发方式,一切都是java对象,想要在网络中传输java对象,可以使用序列化和反序列化去实现,发送发需要将java对象转换为字节序列,然后在网络上传送,接收方收到字符序列后,会通过反序列化将字节序列恢复成java对象。

java序列化的优点:

1.JDK类库提供的序列化API:

序列化要求:

实现序列化的类对象必须实现了Serializable类或Externalizable类才能被序列化,否则会抛出异常。

实现java序列化和反序列化的三种方法:

现在要对student类进行序列化和反序列化,遵循以下方法:

方法一:若student类实现了serializable接口,则可以通过objectOutputstream和objectinputstream默认的序列化和反序列化方式,对非transient的实例变量进行序列化和反序列化。

方法二:若student类实现了serializable接口,并且定义了writeObject(objectOutputStream out)和

readObject(objectinputStream in)方法,则可以直接调用student类的两种方法进行序列化和反序列化。

方法三:若student类实现了Externalizable接口,则必须实现readExternal(Objectinput in)和writeExternal(Objectoutput out)方法进行序列化和反序列化。

JDK类库中的序列化步骤:

第一步:创建一个输出流对象,它可以包装一个输出流对象,如:文件输出流。

ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream("E:\\JavaXuLiehua\\Student\\Student1.txt"));

 第二步:通过输出流对象的writeObject()方法写对象

out.writeObject("hollo word");

out.writeObject("happy")

 JDK中反序列化操作:

第一步:创建文件输入流对象

 ObjectInputStream in = new ObjectInputStream(new fileInputStream("E:\\JavaXuLiehua\\Student\\Student1.txt"));

 第二步:调用readObject()方法

 String obj1 = (String)in.readObject();

 String obj2 = (String)in.readObject();

 为了保证正确读取数据,对象输出流写入对象的顺序与对象输入流读取对象的顺序一致。

 Student类序列化和反序列化演示:

先创建一个继承了serializable类的student类

import java.io.Serializable;            //导入io包下的序列化类//创建实现序列化接口的学生类public class Student implements Serializable {    //私有化成员变量    private String name;    private  char sex;    private  int year;    private  double gpa;    public Student(){   //无参构造    }    public Student(String name,char sex,int year,double gpa){        //参数给属性赋值        this.name = name;        this.sex = sex;        this.year = year;        this.gpa = gpa;    }    //重写set和get    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public char getSex() {        return sex;    }    public void setSex(char sex) {        this.sex = sex;    }    public int getYear() {        return year;    }    public void setYear(int year) {        this.year = year;    }    public double getGpa() {        return gpa;    }    public void setGpa(double gpa) {        this.gpa = gpa;    }}

把Student类的对象序列化到txt文件(E:\\JavaXuLiehua\\Student\\Student1.txt)中,并对文件进行反序列化:

import java.io.*;import java.io.Externalizable;public class UserStudent {    public static void main(String[] args) throws IOException {        Student st = new Student("Tom",'M',20,3.6);         //实例化student类        //判断Student1.txt是否创建成功        File file = new File("E:\\JavaXuLiehua\\Student\\Student1.txt");        if(file.exists()) {            System.out.println("文件存在");        }else{            //否则创建新文件            file.createNewFile();        }        try {            //Student对象序列化过程            FileOutputStream fos = new FileOutputStream(file);            ObjectOutputStream oos = new ObjectOutputStream(fos);            //调用 ObjectOutputStream 中的 writeObject() 方法 写对象            oos.writeObject(st);            oos.flush();        //flush方法刷新缓冲区,写字符时会用,因为字符会先进入缓冲区,将内存中的数据立刻写出            fos.close();            oos.close();            //Student对象反序列化过程            FileInputStream fis = new FileInputStream(file);            //创建对象输入流            ObjectInputStream ois = new ObjectInputStream(fis);            //读取对象            Student st1 = (Student) ois.readObject();           //会抛出异常(类找不到异常)            System.out.println("name = " + st1.getName());            System.out.println("sex = " + st1.getSex());            System.out.println("year = " + st1.getYear());            System.out.println("gpa = " + st1.getGpa());            ois.close();            fis.close();        }catch (ClassNotFoundException e){            e.printStackTrace();        }    }}

 查看txt文件,结果如下:

 sr JavaxulieHua.Studentd9Q藿Hf D gpaC sexI yearL namet Ljava/lang/String;xp@ 烫烫掏 M   t Tom

 可以看出其中的内容是不容易阅读的,只能通过反序列化读取。

transient关键字表示有理的,被修饰的数据不能进行序列化

这里不做详细介绍,修改情况如下:

private transient char sex;         //被transient关键字修饰,不参与序列化

 运行结果如下:

文件存在name = Tomsex =  year = 20gpa = 3.6

此时可以看见,被transient关键字修饰的变量sex并没有被序列化,返回了空值。

Externalizable接口继承Serializable接口,实现Externalizable接口需要实现readExternal()方法和writeExternal()方法,这两个方法是抽象方法,对应的是serializable接口的readObject()方法和writeObject()方法,可以理解为把serializable的两个方法抽象出来。Externalizable没有serializable的限制,static和transient关键字修饰的属性也能进行序列化。

具体代码实现如下:

复制对象student命名为student1,在里面重写writeExternal()方法和readExternal()方法,如下:

   @Override    //对抽象方法进行重写    public void writeExternal(ObjectOutput out) throws IOException{        out.writeObject(name);        out.writeObject(sex);        out.writeObject(year);        out.writeObject(gpa);    }    @Override    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {        name = (String) in.readObject();        sex = (char) in.readObject();        year = (int) in.readObject();        gpa = (double) in.readObject();    }

相应的测试方法里面调用这两种方法的时候,直接调用writeObject()方法和readObject()方法即可,重写的writeExternal()和readExternal()方法会自动执行。

FileOutputStream fos1 = new FileOutputStream(file1);                ObjectOutputStream oos1 = new ObjectOutputStream(fos1);                //调用 ObjectOutputStream 中的 writeObject() 方法 写对象                oos1.writeObject(st);       //会自动执行重写的writeExternal()方法
FileInputStream fis1 = new FileInputStream(file1);                //创建对象输入流                ObjectInputStream ois1 = new ObjectInputStream(fis1);                //读取对象                //会自动执行readExternal()方法                Student1 st1 = (Student1) ois1.readObject();           //会抛出异常(类找不到异常)

虽然student1类里的sex属性被static或transient修饰,但依旧被序列化,结果如下:

文件存在name = Tomsex = Myear = 20gpa = 3.6

来源地址:https://blog.csdn.net/qq_62414755/article/details/125886742

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯