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);
        }
    }
}


相关文章
|
29天前
|
存储 算法 Java
Java HashSet:底层工作原理与实现机制
本文介绍了Java中HashSet的工作原理,包括其基于HashMap实现的底层机制。通过示例代码展示了HashSet如何添加元素,并解析了add方法的具体过程,包括计算hash值、处理碰撞及扩容机制。
【IO面试题 五】、 Serializable接口为什么需要定义serialVersionUID变量?
serialVersionUID用于标识类的序列化版本,确保在反序列化时类的版本一致性,避免因类定义变更导致的不兼容问题。
|
3月前
|
SQL Java 数据库
@Transactional 用法和原理
@Transactional 用法和原理
|
3月前
|
存储 Java
|
Java 调度
Java中synchronized:特性、使用、锁机制与策略简析
Java中synchronized:特性、使用、锁机制与策略简析
|
存储 Java
Serializable接口的意义和用法
Serializable接口的意义和用法
|
JSON Java 数据库连接
87. Java序列化和反序列化为什么要实现Serializable接口
87. Java序列化和反序列化为什么要实现Serializable接口
193 0
|
JSON Java 数据库连接
面试官问:Java 序列化和反序列化为什么要实现 Serializable 接口?什么鬼??
面试官问:Java 序列化和反序列化为什么要实现 Serializable 接口?什么鬼??
242 0
|
存储 缓存 安全
【小家java】HashMap原理、TreeMap、ConcurrentHashMap的原理、性能、安全方面大解析-----看这一篇就够了(上)
【小家java】HashMap原理、TreeMap、ConcurrentHashMap的原理、性能、安全方面大解析-----看这一篇就够了(上)
【小家java】HashMap原理、TreeMap、ConcurrentHashMap的原理、性能、安全方面大解析-----看这一篇就够了(上)
|
存储 安全 算法
【小家java】HashMap原理、TreeMap、ConcurrentHashMap的原理、性能、安全方面大解析-----看这一篇就够了(下)
【小家java】HashMap原理、TreeMap、ConcurrentHashMap的原理、性能、安全方面大解析-----看这一篇就够了(下)
【小家java】HashMap原理、TreeMap、ConcurrentHashMap的原理、性能、安全方面大解析-----看这一篇就够了(下)