1.让要写入的类实现 Serializable接口,这是一个标记接口,只有实现了这个接口的类才能被序列化,这个思想类似于Cloneable接口,实现了这个接口就表示可以被克隆
/* (1)如果没有实现,此时会报出没有序列化异常 NotSerializableException,需要让要写入的对象
实现序列化接口*/
class Student implements Serializable {//实现序列化接口Serializable
private String name;
private Integer age;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
(2)
新建一个写的方法
public static void write()throws Exception{
//需求:要把对象写入到文件:stu.txt中
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("stu.txt"));
Student stu=new Student("张三",14);
oos.writeObject(stu);
}
效果:
(3)这样就成功了,但会发现文件中的对象是乱码的,这个没有关系,这个是系统本身的设计,是为了让数据更加安全,如果我们想把它读出来.可以使用 ObjectInputStream 这个流,即反序列化
新建一个读的方法:
public static void read()throws Exception{
//这样就写入成功了,我们可以通过反序列化把它读取出来
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("stu.txt"));
Object obj=ois.readObject();
if(obj instanceof Student){
Student stu1=(Student)obj;
System.out.println(stu1.getName()+"|"+stu1.getAge());
}
}
}
效果:
(4)至此,已经写完和读完了,但是仍然存在两个隐患,需要我们去完善
问题一:如果我写完后,修改了类中的任意一个地方,再去读,就会发现读不出来了,会报InvalidClassException:这样一个异常
原因分析:我们来理一下刚才的操作:
第一步:
我们在通过序列化流将对象写入文件,那么这个对象保存在文件中,会有一个编号来标识对象
stream classdesc serialVersionUID = 1268963545368942282
local class serialVersionUID=1268963545368942282
第二步:
我们通过反序列化流读取文件,在反序列化之前,会先判断文件中的对象的序列化ID和本地class文件的序列化ID是否匹配,如果匹配,则反序列化对象
第三步:
修改了源文件后,重新编译java,生成class文件,重新生成class序列化id,local class serialVersionUID = -7770128259322463329
第四步:
当你在反序列化的时候,会先判断文件中的对象序列化id和本地class文件的序列化id是否匹配,不匹配,就会排除异常:InvalidClassException
解决办法:
让序列化持久化,在要序列化的类中加一个序列号成员变量,这样要通过快捷键生成
方法:选中类名,按alt+enter
如果没有出现这个,可以根据以下图片进行配置
效果如下:
这样就解决了问题一了
问题二:既然我们对象写入文件中会乱码是为了安全,那我们可以通过反序列化流将数据读取出来,岂不是又让数据不安全了,
解决办法:在不想被读取出来的成员变量中加修饰符:transient,这样读取出来就是null了
效果:
总结:
三个步骤:
(1)实现序列化接口,异常:NotSerializableException
(2)生成序列号:InvalidClassException
(3)加transient修饰符,让数据变安全: