持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
-
序列化:把对象转换成二进制数据,以便于持久化或网络传输
-
反序列化:从网络/磁盘读取读取字节序列然后转化为对象或者数据结构
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);
}
}
}