序列化
- 序列化:将对象写入IO流
- 反序列化:从IO流中恢复对象
- 意义:序列化是将对象转为字节序列,这些字节序列可以保持到磁盘,或通过网络传输。序列化使得对象可以脱离程序的运行而独立存在。
- 使用场景:
- 对象需要保存到磁盘
- 对象需要进行网络传输
具体实现
实现 Serializable 接口
Serializable是一个标记接口,不需要实现任何方法,实现该接口的类可以被序列化。
序列化对象Demo
该程序会将 user 对象序列化并保持到磁盘,后续读取文件并反序列化成 user 对象,并在控制台打印。
public class User implements Serializable {
private static final long serialVersionUID = -2094887379183864867L;
private String name;
private int age;
private String addr;
public User(String name, int age, String addr) {
this.name = name;
this.age = age;
this.addr = addr;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append(", addr='").append(addr).append('\'');
sb.append('}');
return sb.toString();
}
}
public class SerializableTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 序列化
FileOutputStream fileOutputStream = new FileOutputStream("D:\\temp.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
User user = new User("dkangel", 24, "China");
System.out.println(user);
objectOutputStream.writeObject(user);
// 反序列化
FileInputStream fileInputStream = new FileInputStream("D:\\temp.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
user = (User) objectInputStream.readObject();
System.out.println(user);
}
}
控制台输出:
User{name=‘dkangel’, age=24, addr=‘China’}
User{name=‘dkangel’, age=24, addr=‘China’}
文件内容:
sr mytest.serializabletest.User忭wK筝 I ageL addrt Ljava/lang/String;L nameq ~ xp t Chinat dkangel
方法、类变量无法序列化
User对象添加静态变量 school
执行main方法,查看序列化文件,可以看到不包含 school 属性
sr mytest.serializabletest.User忭wK筝 I ageL addrt Ljava/lang/String;L nameq ~ xp t Chinat dkangel
使用 transient 修饰的属性无法序列化
User对象,用 transient 修改addr属性
执行main方法,查看控制台输出
User{name=‘dkangel’, age=24, addr=‘China’}
User{name=‘dkangel’, age=24, addr=‘null’}
查看序列化文件,可以看到不包含addr属性
sr mytest.serializabletest.User忭wK筝 I ageL namet Ljava/lang/String;xp t dkangel
序列化版本号
private static final long serialVersionUID = -2094887379183864867L;
如果不显示指定序列化版本号,JVM会根据类信息自己计算一个版本号,缺点如下:
- 随着class的升级,无法正确反序列化
- 不利于JVM间的移植,可能类没有被修改,但是由于计算规则不同导致序列化ID不同,导致无法反序列化