需求:在保存数据的时候,还要保存这个数据的数据类型。
例如:1.将int num=100这个int数据保存到文件中,注意不是100数字,而是int类型的100,并且能够从文件中直接恢复int 100。2.将Dog dog=new Dog(“小黄”,3)这个对象保存到文件中,并且能够从文件中恢复
上面的要求,就是能够将 基本数据类型 或者 对象 进行序列化和反序列化操作。
ObjectOutputStream提供序列化功能,ObjectInputStream提供反序列化功能。
序列化和反序列化
1.序列化就是在保存数据时,保存数据的值和数据类型
2.反序列化就是在恢复数据时,恢复数据的值和数据类型
3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让该类是可序列化的,该类必须实现如下两个接口之一:Serializable(这是一个标记接口),Externalizable(该接口有方法需要实现,因此我们推荐第一个接口)
标记接口是没有任何方法和属性的接口,只有一个声明性质。
ObjectOutputStream
会乱码,因为序列化后,保存的文件格式,不是纯文本的,而是按照他的格式保存的。
public class ObjectStream { public static void main(String[] args) { //序列化后,保存的文件格式,不是纯文本的,而是按照他的格式保存的 String filepath="D:file-studydata.txt"; ObjectOutputStream objectOutputStream=null; try { objectOutputStream = new ObjectOutputStream(new FileOutputStream(filepath)); //写序列化数据到文件中 objectOutputStream.write(100);//int->Integer(实现了serializable) objectOutputStream.writeBoolean(true);//boolean->Boolean(实现了serializable) objectOutputStream.writeDouble(9.6);//double->Double(实现了serializable) objectOutputStream.writeUTF("沈11");//String实现了serializable //保存一个dog对象 objectOutputStream.writeObject(new Dog("小黄",3)); } catch (IOException e) { throw new RuntimeException(e); }finally { try { objectOutputStream.close(); System.out.println("序列化完成"); } catch (IOException e) { throw new RuntimeException(e); } } }}class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; }}
ObjectInputStream
public class ObjectInput { public static void main(String[] args) throws IOException, ClassNotFoundException { //指定反序列化文件 String filepath="D:file-studydata.dat"; ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream(filepath)); //读取数据(反序列化)的顺序需要和你保存数据(序列化)的顺序一致 System.out.println(objectInputStream.readInt()); System.out.println(objectInputStream.readBoolean()); System.out.println(objectInputStream.readDouble()); System.out.println(objectInputStream.readUTF()); //dog的编译类型为Object Object dog=objectInputStream.readObject(); System.out.println(dog); //这里是特别重要的细节 //如果我们希望调用Dog方法,需要向下转型 Dog dog1=(Dog)dog; System.out.println(dog1.getAge()); System.out.println(dog1.getName()); //关闭流 objectInputStream.close(); }}
对象处理流的注意事项
1.读写顺序要一致
2.要求实现序列化或反序列化对象,需要实现Serializable
3.序列化对象时,要求里面属性的类型也需要实现序列化接口。
4.serialVersionUID是序列化的版本号,可以提高兼容性,当你的类中添加新的属性时,在处理过程中,它会认为这个类只是版本的修改,而不是一个全新的类。
private static final long serialVersionUID=1L
5.static或transient修饰的属性不会被保存,因为static属于类,而不属于对象。
6.序列化具有可继承性。
System.out和System.in 标准输入输出流
//System类的 public final static InputStream in = null; //System.in 编译类型 InputStream //System.in 运行类型 BufferedInputStream 字节流 //System.in表示标准输入,也就是键盘 System.out.println(System.in.getClass()); //System类的 public final static PrintStream out = null; //System.out 编译类型:PrintStream //System.out 运行类型:PrintStream //System.out表示标准输出 也就是显示器 System.out.println(System.out.getClass()); Scanner scanner=new Scanner(System.in);