IO-----序列化和反序列化
当我们把一个对象的信息存储到我们的硬盘的软件当中的时候,我们肯定不想让别人直接就可以打开文件看懂我们存储的
对象的信息,所以这时候我们就用到了输入输出流之中的对象操作流:
- ObjectOutputStream对象输出流
- ObjectInputStream对象输入流
顾名思义Object就是代表对象,所以这两个流主要就是用来操作对象的。
如果我们想让我们的对象存储到硬盘中是下面的这种别人看不懂的文字:
我们就需要借助对象输出流。
我们借助一个案例来分析:
案例:
创建一个学生javabean类,属性有姓名,性别,年龄,分数,并创建一个学生对象,然后把学生对象的信息储存到本项目下的test5_1.txt文件中,然后在我们需要的时候从
test5_1.txt文件中读取存储过得学生对象的信息。
分析:
- 把学生对象的信息存储文件中的过程是序列化过程
- 把信息从文件中读取出来是反序列化的过程
那么我们先解决序列化的过程:
首先需要创建一个学生对象(注意这个对象的创建是有猫腻的)
代码:
学生类对象:
public class Student implements Serializable {//如果一个类想要被序列化则必须要实现Serializable接口 private static final long serialVersionUID = 1L;//将本类的序列号固定 private String name; private String sex; private int age; private int result; public Student() { } public Student(String name, String sex, int age, int result) { this.name = name; this.sex = sex; this.age = age; this.result = result; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getResult() { return result; } public void setResult(int result) { this.result = result; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", age=" + age + ", result=" + result + '}'; }
一个类的对象如果想要被序列化
- 就一定要实现Serializable接口
implements Serializable
如果在序列化和反序列化的过程中javabean类的内容有多修改,反序列化还想要成功
- 就将本类的序列号写死
private static final long serialVersionUID = 1L;
接下来我们开始用对象输出流对学生对象进行序列化操作:
代码:
public static void main(String[] args) throws IOException { Student stu = new Student("迪丽热巴", "女", 18, 98); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test5_1.txt"));//创建一个对象输出流 oos.writeObject(stu);//注意方法是writeObject,顾名思义,直接写对象 oos.close();//关流 }
运行后将对象序列化文件中的结果是:
我相信绝大多数人是看不懂的,所以这样就大大的提高了信息的安全性
接下来我们再讲反序列化:
先看反序列化代码:
public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test5_1.txt"));//获取对象输入流 Student stu = (Student) ois.readObject();//反序列化并强转成对象 System.out.println(stu); ois.close(); }
输出结果:
但是我们如果在反序列化之前对javabean类中信息进行修改了,还会不会反序列化成功呢?
这就是我上面提到的序列号固定问题:
- 一个对象在被序列化的过程中jvm虚拟机会根据javabean类的信息计算出其对应的序列号
- 那么我们再序列化之后存储在文件中的信息也会被保存一份序列号
- 当我们在反序列化之前改变javabean类的信息就会改变javabean的序列号
- 那么反序列化的时候文件中信息中存储的序列号就和原来对应的javabean类的序列号就不在同
- 所以反序列化就会失败
- 如果我们让序列号写死:private static final long serialVersionUID = 1L;那么反序列化就不会出现错误了。
对于序列号写死代码private static final long serialVersionUID = 1L;我们其实不必死记硬背:这里告诉大家一个诀窍:
在IDEA中输入ArrList按住ctrl点击进入ArrList源码:
把数字修改一下不超过long的范围就行了。。。。。。。。
迎风少年