对象序列化流的问题
对象序列化流的三个问题,如下
1、用对象序列化流,序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢? a_12_2Student实现了Serializable接口,则a_12_2Student会有一个序列化id。 序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID。
serialVersionUID:在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与该序列化兼容的该对象的类。 如果接收者已经为具有与相应发送者类别不同的serialVersionUID的对象加载了类,则反序列化将导致InvalidClassException异常。
2、如果出问题了如何解决呢 解决:序列化类必须声明显式serialVersionUID值,即在学生类里面加上右边这一行private static final long serialVersionUID = 42L。 注意:右边的42L是可以修改的,不一定非要42L
3、如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢? 解决:给这个age成员变量加上一个关键字transient来修饰
对象序列化流问题的练习
xxxxxxxxxxpackage ch20;
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;
public class a_12_1测试 {
public static void main(String[] args) throws IOException, ClassNotFoundException { write();//先调用写数据的方法 //把上面那行注释掉,去修改类文件,会发现这里的程序报错InvalidClassException //注意,如果你的程序没报错,那么请按照右边这个顺序再操作一遍:先不重写toString,去运行一次这里的write()和read(),再重写toString,最后运行,必报错 read();//再调用读数据的方法 }
//反序列化 private static void read() throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\huanf\\java\\src\\ch18_ch19_储物区\\oos2.txt")); Object obj = ois.readObject(); a_12_2Student s = (a_12_2Student) obj; System.out.println(s.getName()+","+s.getAge()); ois.close(); }
//序列化 private static void write() throws IOException { //ObjectOutputStream不能追加数据 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\huanf\\java\\src\\ch18_ch19_储物区\\oos2.txt")); a_12_2Student s = new a_12_2Student("李四",19); oos.writeObject(s); oos.close(); }
}xxxxxxxxxxpackage ch20;
import java.io.Serializable;
//a_12_2Student实现了Serializable接口,则a_12_2Student会有一个序列化id//序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID//serialVersionUID:在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与该序列化兼容的该对象的类//如果接收者已经为具有与相应发送者类别不同的serialVersionUID的对象加载了类,则反序列化将导致InvalidClassException异常//解决:序列化类必须声明显式serialVersionUID值,即在学生类里面加上右边这一行private static final long serialVersionUID = 42L 。如下11行处public class a_12_2Student implements Serializable {//Serializable接口报红线,因为该接口在java.io包下,所以需要导包才能使用 private static final long serialVersionUID = 42L; //加上这行就解决了。如果想刚学习就建议把这行注释掉,自己亲身感受一下报错 //如果还报错,那么去把测试类的write和read解开运行一次,然后就正常了,然后这个学生类随便你怎么修改,测试类都不会报错
//成员变量 private String name; private transient int age; //如果age不想被序列化,怎么实现呢,即在测试类的控制台不会输出年龄。解决:给这个age成员变量加上一个关键字transient //如果测试类的控制台输出的年龄是0,就说明解决成功了
//无参构造方法 public a_12_2Student() { }
//带参构造方法 public a_12_2Student(String name, int age) { this.name = name; this.age = age; }
//成员变量对应的get/set方法 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; }
//按Alt+Insert,选toString(),生成方法。就相当于我们修改了类文件 public String toString() { return "a_12_2Student{" + "name='" + name + '\'' + ", age=" + age + '}'; }}