详解Java 序列化与反序列化

观前提示:

本文所使用的Eclipse版本为Photon Release (4.8.0),IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141,Tomcat版本为9.0.12。

1.基本概念

1.1 定义

序列化:把对象转换为字节序列的过程称为对象的序列化。

反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

1.2 用途

  1. 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中。

  2. 在网络上传送对象的字节序列。

2.实现序列化和反序列化

2.1 JDK类库中序列化API

JDK中关键类 ObjectOutputStream(对象输出流)ObjectInputStream(对象输入流)

ObjectOutputStream 类:通过使用 writeObject(Object object) 方法,将对象以二进制格式进行写入。

ObjectInputStream 类:通过使用 readObject()方法,从输入流中读取二进制流,转换成对象。

2.2 实现Serializable接口

这个对象的所有属性(包括private属性、包括其引用的对象)都可以被序列化和反序列化来保存、传递。不想序列化的字段可以使用transient修饰。

例子如下

实现Serializable接口的Person.java

package testSerialize;

import java.io.Serializable;

public class Person implements Serializable {
    
    

    private static final long serialVersionUID = 1351786752651948395L;

    private String id;
    private String name;
    private transient int age;

    public String getId() {
    
    
        return id;
    }

    public void setId(String id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试类Test.java

package testSerialize;

import java.io.*;

public class Test {
    
    

    public static void main(String[] args){
    
    

        // 序列化
        Person person = new Person();
        person.setId("123456");
        person.setName("张三");
        person.setAge(18);
        // ObjectOutputStream输出流,将Person对象存储到文件中,实现序列化
        ObjectOutputStream os = null;
        try {
    
    
            os = new ObjectOutputStream(new FileOutputStream("D:test.txt"));
            os.writeObject(person);
            os.close();
        } catch (Exception e){
    
    
            e.printStackTrace();
        } finally {
    
    
            if (os != null){
    
    
                try {
    
    
                    os.close();
                } catch (Exception e){
    
    

                }
            }
        }
        System.out.println("--------------------序列化完成--------------------");

        // 反序列化
        ObjectInputStream is = null;
        try {
    
    
            is = new ObjectInputStream(new FileInputStream("D:test.txt"));
            Person p = (Person) is.readObject();
            System.out.println(p.toString());
        } catch (Exception e){
    
    
            e.printStackTrace();
        } finally {
    
    
            if (is != null){
    
    
                try {
    
    
                    is.close();
                } catch (Exception e){
    
    

                }
            }
        }
        System.out.println("--------------------反序列化完成--------------------");
    }
}

运行结果如下
在这里插入图片描述

保存文件内容为我们看不懂的序列化后的东西
在这里插入图片描述

注意

  1. Serializable 接口的作用只是用来标识我们这个类是需要进行序列化,并且 Serializable 接口中并没有提供任何方法。

  2. SerialVersionUid 序列化版本号的作用是用来区分我们所编写的类的版本,用于判断反序列化时类的版本是否一直,如果不一致会出现版本不一致异常。

  3. transient 关键字,主要用来忽略我们不希望进行序列化的变量

2.3 实现Externalizable 接口

它是Serializable接口的子类,用户要实现的==writeExternal()readExternal() ==方法,用来决定如何序列化和反序列化。

猜你喜欢

转载自blog.csdn.net/weixin_43611145/article/details/108715676