对象流
- 对象流基本理解
当我们保存一个int 类型的数据100时,我们在文件中只能看见数字100,但不知道这个100是int类型的还是String引用类型 ,而且我们需要把一个对象存储在文件中并能从文件中恢复,这个时候我们就需要使用对象输入输出流,就是能够把基本数据类型或对象进行序列化和反序列化。
- 序列化和反序列化
序列化:就是在保存数据的时,保存数据的值和数据类型
反序列化:就是在恢复数据时,恢复数据的值和数据类型
在Java中需要让某个对象支持序列化机制,必须让其类是可序列化的,想让一个类可序列化我们必须实现接口Serializable(一般用这个,为标记接口没有方法)或Externalizable
- 对象流注意事项
- 读写顺序一致(序列化或者反序列化时序列数据的顺序必须是一致的)
- 要求实现序列化或者反序列化必须实现Serializable
- 序列化中建议添加SerialVersionUID为了提高版本的兼容性
- 序列化对象时默认将里面的所有属性都进行了序列化,处理static和transient修饰的变量
- 序列化对象时要求里面的属性的类型也需要实现序列化接口(public Run run;这里的Run类也需要实现序列化接口)
- 序列化具有可继承性,也就是如果某个类实现了序列化接口那么他的子类相当于默认实现了序列化接口
ObjectOutputStream
- 代码示例
public static void main(String[] args) throws IOException {
//在序列化保存的文件格式不是纯文本,是按照保存的对象的格式来进行保存的
String filePath="E:/IOFile/news3.dat";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到文件news3.dat中
objectOutputStream.writeInt(1); //将int类型包装成Integer(实现了Serializable)
objectOutputStream.writeBoolean(true);//bollean-->Bollean(实现了Serializable)
objectOutputStream.writeChar('a'); //char-->Character(实现了Serializable)
objectOutputStream.writeDouble(3.14); //double-->Double(实现了Serializable)
objectOutputStream.writeUTF("IO流"); //为String类型(实现了Serializable)
objectOutputStream.writeObject(new Person("张三",14));
System.out.println("保存成功");
objectOutputStream.close();
}
//实现person类
//这里不实现Serializable接口会报出无法序列化异常
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
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;
}
}
ObjectInputStream
- 代码示例
读取(反序列化)数据过程的顺序必须和写入(序列化)数据的过程的顺序一样
public static void main(String[] args) throws IOException, ClassNotFoundException {
String filePath="E:/IOFile/news3.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//读取(反序列化)数据过程的顺序必须和写入(序列化)数据的过程的顺序一样
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
//这里的person编译时是Object类型的,运行时是Person类型的
Object person=ois.readObject();//报出类找不到异常
Person person1=(Person)person;
System.out.println("perosn类信息: "+person);
System.out.println("运行类型: "+person.getClass());
System.out.println(person1.getName());
ois.close();
}
- 部分异常原因和处理办法
- 1.出现该异常是因为我们在序列化的代码中添加了新的代码,但是我们没有重写运行序列化,序列化还是上一次序列化的结果,列如我一开始没有在person类中重写toString()方法,当我发现在反序列化中,我想输出的类的信息输出的却不是,发现是在person类中没有重写toString()方法后,我就直接重写了,在去运行反序列化发现报出此异常,重新运行序列化过程发现运行成功
- 2.出现该异常是因为序列化之后的包的路径和反序列化之后包的路径不同,也就是person类不在一个包下