3.4. 对象流与序列化

一. 序列化和反序列化的理解

什么是序列化?

序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据

image.png|500

二. 通过对象专属流实现序列化

一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。

参与序列化和反序列化的对象,必须实现Serializable接口

注意:
通过源码发现,Serializeable 接口只是一个标志接口

public interface Serializable{
}

这个接口什么代码都没有,那么他有什么作用呢?
起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,会对这个类进行特殊待遇,JVM看到 Serializeable 接口后,会为该类自动生成一个序列化版本号

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectOutputStreamTest {
    public static void main(String[] args) throws Exception {
        //创建对象
        Student s = new Student(1111,"zhangsan");
        //序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));

        //序列化对象
        oos.writeObject(s);

        oos.flush();
        oos.close();
    }
}

三. 序列化版本号

Java虚拟机会默认提供序列版本号。如果类的源代码改动之后,需要重新编译,编译之后生成了全新的字节码文件。并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改变

建议将序列版本号手动写出来,不建议自动生成

class Student implements Serializable {

private static final long serialVersionUID = 1L;//手动写出序列号
        
private int no;
private String name;

1. java语言是采用什么样的机制来区分分类的?

  • 第一:首先通过类名进行比对,如果类名不一样,肯定不是同一个类


  • 第二:如果类名一样,靠序列化版本号进行区分。


小鹏编写了一个类: com . Bjipowernode . Java. Bean. Student implements Serial izable 胡浪编写了一个类: com . Bjpowernode. Java. Bean. Student implements Serial izable

不同的人编写了同一个类,但“这两个类确实不是同一个类”。这个时候序列化版本就起上作用了。

对于 java 虚拟机来说, java 虚拟机是可以区分开这两个类的, 因为这两个类都实现了 Serializable 接口, 都有默认的序列化版本号, 他们的序列化版本号不一样。所以区分开了。( 这是自动生成序列化版本号的好处)

这种自动生成序列化版本号有什么缺陷?

这种自动生成的序列化版本号缺点是: 一旦代码确定之后,不能进行后续的修改,因为只要修改, 必然会重新编译, 此时会生成全新的序列化版本号, 这个时候 java 虚拟机会认为这是一个全新的类。( 这样就不好了! )

结论:

凡是一个类实现了 Serializable 接口,建议给该类提供一个固定不变的序列化版本号

这样,即使以后这个类代码修改了,但是版本号不变,java 虚拟机会认为是同一个类

2. IDEA生成序列化版本号

File -> Settings -> Editor -> Inspections -> 搜索 serializable-> 选中Serializable classes Without a serialVersionUID -> Apply

image.png|750

然后再类名上:Alt+回车

image.png|500

四. 通过对象专属流实现反序列化

import java.io.Serializable;

class Student implements Serializable {
        private int no;
        private String name;

        public Student(int no, String name) {
            this.no = no;
            this.name = name;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "no=" + no +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ObjectInputStreamTest {
    public static void main(String[] args) throws  Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
        //开始反序列化
        Object obj = ois.readObject();
        //反序列化回来是一个学生对象,所以会调用学生对象的toString方法
        System.out.println(obj);
        ois.close();

    }
}
image.png|500

五. 序列化多个对象

把对象放入集合中去,序列化集合。

class User implements Serializable {
    private int no;
    private String name;

    public User() {
    }

    public User(int no, String name) {
        this.no = no;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class ObjectOutputStreamTest2 {
    public static void main(String[] args) throws IOException {
        List<User> userList = new ArrayList<>();
        userList.add(new User(1,"zhangsan"));
        userList.add(new User(2,"lisi"));
        userList.add(new User(3,"wangwu"));
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users"));

        //序列化一个集合,这个集合对象中放了很多其他的对象
        oos.writeObject(userList);

        oos.flush();
        oos.close();
    }
}
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

public class ObjectInputStreamTest2 {
    public static void main(String[] args) throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users"));
        List<User> userList = (List<User>)ois.readObject();
        for(User users: userList){
            System.out.println(users);
        }

        ois.close();
    }
}

运行结果:

image.png|500

六. transient关键字

transient关键字表示游离的,不参与序列化

User类加入 transient 关键字修改:

private transient String name;

再次运行结果:

image.png|500

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇