- 序列化:把对象转换成二进制数据,以便于持久化或网络传输
- 反序列化:从网络/磁盘读取读取字节序列然后转化为对象或者数据结构
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(); } } } 复制代码
- 在序列化反序列化过程中,父类没有实现序列化接口,那么父类的属性将不会参与到序列化反序列化的过程中,父类需要提供无参构造函数来重新创建对象
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); } } }