public class Student implements Serializable {
//java虚拟机看到Serializable接口后,会自动生成一个序列化版本号
//这里没有手动写出来,java虚拟机会默认提供这个序列化版本号
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ObjectOutputStreamTest01 {
public static void main(String[] args) throws Exception {
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\io\\objectoutputstream\\students"));
//序列化对象
oos.writeObject(new Student("zhangsan",18));
//flush close
oos.flush();
oos.close();
}
}
public class ObjectInputStreamTest01 {
public static void main(String[] args) throws Exception{
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\io\\objectoutputstream\\students"));
//反序列化对象,返回一个学生对象,所以会调用学生对象的toString方法
System.out.println(ois.readObject());
//close
ois.close();
}
}
//运行结果:
Student{name='zhangsan', age=18}
/*
建议将序列化版本号手动写出来,不建议自动生成
*/
public class User implements Serializable {
private static final long serialVersionUID = -15920575867251947L;
//transient:游离的,不参与序列化
String name;
transient int age; //age不参与序列化
int id;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
public class ObjectOutputStreamTest02 {
public static void main(String[] args) throws Exception{
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\io\\objectoutputstream\\Users"));
//创建集合
List<User> userList = new ArrayList<>();
//向集合中添加对象
userList.add(new User("张三",18));
userList.add(new User("李四",20));
//序列化集合对象
oos.writeObject(userList);
//flush close
oos.flush();
oos.close();
}
}
public class ObjectInputStreamTest02 {
public static void main(String[] args) throws Exception{
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\io\\objectoutputstream\\Users"));
//创建集合
List<User> list;
//反序列化对象
list = (List<User>) ois.readObject();
//遍历
for (User user : list){
System.out.println(user);
}
//close
ois.close();
}
}
//运行结果:
User{name='张三', age='0'}
User{name='李四', age='0'}
修改对象类文件后,如果不重新序列化,会出InvalidClassException异常
Exception in thread “main” java.io.InvalidClassException:
io.objectoutputstream.User; local class incompatible:
stream classdesc serialVersionUID = -3965806672486621565, //修改后
local class serialVersionUID = -15920575867251947 //修改前
为了避免上述异常的发生,建议手动添加序列化版本号
java语言中是采用什么机制来区分类的
第一:首先通过类名来进行对比,如果类名不一样,肯定不是同一个类
第二:如果类名一样,再怎么进行类的区别?靠序列化版本号进行区分
不同的人编写了同一个类,但“这两个类确实不是同一个类”,这时序列化版本就起上作用了
对于java虚拟机来说,java虚拟机是可以区分开这两个类的,因为这两个类都实现了Serializable接口
都有默认的序列化版本号,他们的序列化版本号不一样。所以区分开了
这种自动生成序列化版本号有什么缺陷:
一旦代码确定之后,不能进行后续的修改,因为只要修改,必然会重新编译,
此时会生成全新的序列化版本号,这个时候java虚拟机会认为这是一个全新的类
最终结论:
凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号
这样,以后这个类即使代码修改了,但是版本号不变,java虚拟机会认为是同一个类
使用IDEA工具添加序列化版本号的方法:
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务