Serializable工作原理

简介: Serializable工作原理
  • 序列化:把对象转换成二进制数据,以便于持久化或网络传输
  • 反序列化:从网络/磁盘读取读取字节序列然后转化为对象或者数据结构

Serializable接口

/**
 * @see java.io.ObjectOutputStream
 * @see java.io.ObjectInputStream
 * @see java.io.ObjectOutput
 * @see java.io.ObjectInput
 * @see java.io.Externalizable
 * @since   1.1
 */
public interface Serializable {
}
复制代码

Serializable是一个空接口,所有实现Serializable接口的对象都可以被ObjectOutputStream序列化,以及被ObjectInputStream反序列化

Serializable接口特点

  • 序列化类的属性没有实现 Serializable 那么在序列化就会报错
public class User {
    private String name;
    private int age;
    public static void main(String[] args) throws IOException {
        try (ObjectOutputStream outputStream =
                new ObjectOutputStream(new FileOutputStream("User.txt"))) {
            User user = new User();
            user.name = "zouwei";
            user.age = 22;
            outputStream.writeObject(user);
            outputStream.flush();
        }
    }
}
复制代码

image.png

  • 在序列化反序列化过程中,父类没有实现序列化接口,那么父类的属性将不会参与到序列化反序列化的过程中,父类需要提供无参构造函数来重新创建对象
public class Animal {
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
public class Dog extends Animal implements Serializable {
    private static final long serialVersionUID = -8559877565455401808L;
    private String name;
    public static void main(String[] args) throws Exception {
        // 序列化
        serialObject();
        // 反序列化
        deserialObject();
    }
    private static void serialObject() throws IOException {
        try (ObjectOutputStream outputStream =
                new ObjectOutputStream(new FileOutputStream("Dog.txt"))) {
            Dog dog = new Dog();
            dog.name = "Black";
            dog.setAge(2);
            outputStream.writeObject(dog);
            outputStream.flush();
        }
    }
    private static void deserialObject() throws Exception {
        try (ObjectInputStream inputStream =
                new ObjectInputStream(new FileInputStream("Dog.txt"))) {
            Dog dog = (Dog) inputStream.readObject();
            System.out.println(dog.name + ":" + dog.getAge());
        }
    }
}
复制代码
序列化前:
name:Black
age:2
反序列化后:
name:Black
age:0
复制代码
  • 静态成员变量是不能被序列化的
序列化是针对对象属性的,而静态成员变量是属于类的
复制代码
  • transient修饰的对象成员变量不参与序列化
  • 自定义序列化、反序列化方式。
    要想解决transient或者静态成员变量不能序列化或反序列化的问题,可以自定义序列化和反序列化
public class Dog implements Serializable {
    private static final long serialVersionUID = -8559877565455401808L;
    private transient String value;
    private String name;
    private void writeObject(ObjectOutputStream out) throws IOException {
        // 先调用jvm默认序列化操作
        out.defaultWriteObject();
        out.writeObject(this.value);
    }
    private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
        // 使用jvm默认的反序列化操作
        input.defaultReadObject();
        this.value = (String) input.readObject();
    }
    public static void main(String[] args) throws Exception {
        // 序列化
        serialObject();
        // 反序列化
        deserialObject();
    }
    private static void serialObject() throws IOException {
        try (ObjectOutputStream outputStream =
                new ObjectOutputStream(new FileOutputStream("Dog.txt"))) {
            Dog dog = new Dog();
            dog.name = "Black";
            dog.value = "transient";
            outputStream.writeObject(dog);
            outputStream.flush();
        }
    }
    private static void deserialObject() throws Exception {
        try (ObjectInputStream inputStream =
                new ObjectInputStream(new FileInputStream("Dog.txt"))) {
            Dog dog = (Dog) inputStream.readObject();
            System.out.println("name:" + dog.name + "\nvalue:" + dog.value);
        }
    }
}
复制代码

serialVersionUID的作用

serialVersionUID是用于确保序列化与反序列化的兼容性问题,如果序列化和反序列化过程中这两个值不一样,那么将导致序列化失败。
复制代码

Externalizable接口

实现Externalizable是另一种自定义序列化、反序列化的方式

public class Dog implements Externalizable {
    private static final long serialVersionUID = -8559877565455401808L;
    private transient String value;
    private String name;
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(this.name);
        out.writeObject(this.value);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.name = (String) in.readObject();
        this.value = (String) in.readObject();
    }
    public static void main(String[] args) throws Exception {
        // 序列化
        serialObject();
        // 反序列化
        deserialObject();
    }
    private static void serialObject() throws IOException {
        try (ObjectOutputStream outputStream =
                new ObjectOutputStream(new FileOutputStream("Dog.txt"))) {
            Dog dog = new Dog();
            dog.name = "Black";
            dog.value = "transient";
            outputStream.writeObject(dog);
            outputStream.flush();
        }
    }
    private static void deserialObject() throws Exception {
        try (ObjectInputStream inputStream =
                new ObjectInputStream(new FileInputStream("Dog.txt"))) {
            Dog dog = (Dog) inputStream.readObject();
            System.out.println("name:" + dog.name + "\nvalue:" + dog.value);
        }
    }
}


相关文章
|
9月前
|
Java 调度
Java中synchronized:特性、使用、锁机制与策略简析
Java中synchronized:特性、使用、锁机制与策略简析
|
12月前
|
存储 Java
Serializable接口的意义和用法
Serializable接口的意义和用法
|
Dubbo Java 应用服务中间件
关于在dubbo分布式种实体类Bean序列化产生的问题和内部类序列化的问题 UserServiceImpl must implement java.io.Serializable
今天在学习RPC dubbo的分布式 在跟老师学习的过程中,产生一个运行时报错,首先看项目结构和关键代码
248 0
关于在dubbo分布式种实体类Bean序列化产生的问题和内部类序列化的问题 UserServiceImpl must implement java.io.Serializable
|
JSON Java 数据库连接
87. Java序列化和反序列化为什么要实现Serializable接口
87. Java序列化和反序列化为什么要实现Serializable接口
163 0
|
存储 Java
Java 核心技术之序列化 Serializable
一、序列化概念 将对象在内存中的状态保存下来,在需要的时候获取。 序列化:将对象转换为字节序列,以便在网络传输或存储。 反序列化:将字节序列转换为对象。
226 0
|
JSON Java 数据库连接
面试官问:Java 序列化和反序列化为什么要实现 Serializable 接口?什么鬼??
面试官问:Java 序列化和反序列化为什么要实现 Serializable 接口?什么鬼??
213 0
|
Java
Java - 序列化和反序列化为什么要实现Serializable接口?(二)
Java - 序列化和反序列化为什么要实现Serializable接口?(二)
99 0
|
JSON Java 数据库连接
Java - 序列化和反序列化为什么要实现Serializable接口?(一)
Java - 序列化和反序列化为什么要实现Serializable接口?(一)
145 0
|
存储 设计模式 Dubbo
Java是如何实现自己的SPI机制的? JDK源码(一)
Java是如何实现自己的SPI机制的? JDK源码(一)
1181 0
Serializable详解(1):代码验证Java序列化与反序列化
Serializable详解之代码验证Java序列化与反序列化

热门文章

最新文章