前言
Serializable是对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。
我们将从以下几个问题来深入了解Serializable。
- 什么是序列化与反序列化?
- 为什么要进行序列化?
- Serializable在序列化过程中起到了什么作用?
1 序列化与反序列化
Java序列化是指把Java对象转换为字节序列的过程。Java反序列化是指把字节序列恢复为Java对象的过程
2 为什么要进行序列化
因为Java的对象本质上就是class字节码,如果你把对象传给服务器这些,它们是不能识别你传的是一个Java对象。所以这个时候,我们就需要一个约定好的格式,让大家都能识别这是一个对象。
这也就是为什么要进行对象序列化。
把对象序列化为一个有序字节序列后,我们不管是存储到文件,还是传输给服务器等,都很方便,大家也都能识别这是一个Java对象。
3 Serializable作用
Serializable接口就是让JVM知道,这个对象要进行序列化。
public interface Serializable {
}
所以这个接口并没有什么方法需要实现。下面我们实际来用一下序列化。
===> 1.定义User类,实现Serializable接口。
public class User implements Serializable {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
===> 2.测试序列化。
public class TestSerializable {
public static void main(String[] args) {
User user = new User("张三", 30);
// 序列化
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("1.txt"));
objectOutputStream.writeObject(user);
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
User user2 = null;
try {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("1.txt"));
user2 = (User) objectInputStream.readObject();
objectInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
// 反序列化后的内容
System.out.println(user2.toString());
// 反序列化后的对象已经不是原来那个
System.out.println(user2.equals(user));
}
}
===> 3.结果如下。
通过这个例子,我们可以清楚看到,对象序列化后,变成了一串字节序列,存到了文件里。
再次去读文件内容,又可以得到一个新的User对象,虽然不是原来那个,但是里面的数据状态是一致的。
最后再说一个点。
一般在序列化时,我们都会在类中定义一个serialVersionUID,如下,private static final long serialVersionUID = 1L;
这个值可以把它看作key,用来处理版本兼容的。
不显式定义这个属性值的坏处
- 不利于程序在不同的JVM之间的移植。因为不同的编译器实现该属性值的计算策略可能不同,从而造成虽然类没有改变,但是因为JVM不同,出现因类版本不兼容而无法正确反序列化的现象出现。
- 如果你把对象写到了文件里,然后你又修改了对象。然后,再用新的对象去读旧文件里的对象就会报错。
显示定义后的效果
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private Integer age2; // 修改 age ==> age2
private String gender; // 增加 gender
public User(String name, Integer age, String gender) {
this.name = name;
this.age2 = age2;
this.gender = gender;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age2=" + age2 +
", gender='" + gender + '\'' +
'}';
}
}
输出:
4 小结
Java的序列化、反序列化最终目的就是让对象变成另一种易于存储易于传输的形式,且又能识别还原回来。
把握这一核心点,用好序列化指日可待。