Java学习笔记(五十 一)—— 序列化流和反序列化流

对象的序列化流ObjectOutputStream
  • 概述
  1. ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。
  2. 只有支持java.io.Serializable接口的对象才能写入流中。 每个可序列化对象的类被编码,包括类的类名和签名,对象的字段和数组的值以及从初始对象引用的任何其他对象的关闭。
  3. 方法writeObject用于将一个对象写入流中。 任何对象,包括字符串和数组,都是用writeObject编写的。 多个对象或原语可以写入流。 必须从对应的ObjectInputstream读取对象,其类型和写入次序相同。
  4. 原始数据类型也可以使用DataOutput中的适当方法写入流中。 字符串也可以使用writeUTF方法写入。
  5. 对象的默认序列化机制写入对象的类,类签名以及所有非瞬态和非静态字段的值。 引用其他对象(除了在瞬态或静态字段中)也会导致这些对象被写入。 使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象的图形恢复为与原始文件相同的形状。
  6. 以流的方式把对象写入文件中,继承OutputStream
  • 构造方法

    protected  ObjectOutputStream​() 
    	为完全重新实现ObjectOutputStream的子类提供一种方法,不必分配刚刚被ObjectOutputStream实现使用的私有数据。  
    ObjectOutputStream​(OutputStream out) 
    	创建一个写入指定的OutputStream的ObjectOutputStream。  
    
  • 成员方法

    void writeObject​(Object obj) 将指定的对象写入ObjectOutputStream。  
    
    使用步骤:
    	1、创建一个ObjectOutputStream对象,构造方法中传递字节输出流
    	2、使用ObjectOutputStream对象的方法write,把对象写入到文件中
    	3、释放资源
    
    /*
        序列化和反序列化的时候会抛出NotSerializableException异常
            类的序列化由实现java.io.Serializable接口的类启用。
            不实现此接口的类将不会使任何状态序列化或反序列化。
            可序列化类的所有子类型都是可序列化的。
            序列化接口没有方法或字段,仅用于标识可串行化的语义。
        要实现类的序列化和反序列化,必须实现Serializable接口
    */
    public class Person implements Serializable {
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.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;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
对象的反序列化流ObjectInputStream
  • 概述
  1. ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。

  2. ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序。 ObjectInputStream用于恢复先前序列化的对象。 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数。

  3. ObjectInputStream确保从流中创建的图中的所有对象的类型与Java虚拟机中存在的类匹配。 根据需要使用标准机制加载类。

  4. 只能从流中读取支持java.io.Serializable或java.io.Externalizable接口的对象。

  5. 方法readObject用于从流中读取对象。 应使用Java的安全铸造来获得所需的类型。 在Java中,字符串和数组是对象,在序列化过程中被视为对象。 读取时,需要将其转换为预期类型。

  6. 把文件中保存的对象以流的方式读取出来,继承了InputStream

  • 构造方法

    protected  ObjectInputStream​() 
    	为完全重新实现ObjectInputStream的子类提供一种方法,不必分配刚刚被ObjectInputStream实现使用的私有数据。  
    ObjectInputStream​(InputStream in) 
    	创建从指定的InputStream读取的ObjectInputStream。  
    
  • 成员方法

    Object readObject​() 从ObjectInputStream读取一个对象。  
    
    使用步骤:
    	1、创建ObjectInputStream对象,构造方法中传入字节输入流
    	2、使用ObjectInputStream对象中的方法readObject方法读取保存对象的文件
    	3、释放资源
    	4、使用读取出来的对象
    
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day15\\src\\person.txt"));
            System.out.println(ois.readObject());
        } catch (Exception e) {
            e.printStackTrace();
        }
    
transient关键字
  • static 关键字:
    • 被static修饰的成员变量不能被序列化
    • 静态关键字
    • 静态优先于非静态加载到内存中
  • transient关键字:
    • 瞬态关键字
    • 被 transient修饰的成员变量不能被序列化
异常处理
  • InvalidClassException
    /*
    		序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID,
    	它在反序列化过程中使用,以验证序列化对象的发送者和接收者是否加载了与序列化兼容的
    	对象的类。 如果接收者已经为具有与对应发件人类别不同的serialVersionUID的对象加
    	载了一个类,则反序列化将导致一个InvalidClassException 。 一个可序列化的类可以
    	通过声明一个名为"serialVersionUID"的字段来显式地声明它自己的serialVersionUID,
    	该字段必须是static,final和long类型:
    */
    private static final long serialVersionUID =1L;
    
案例
  • 序列化集合
    public class Person implements Serializable {
        private static final long serialVersionUID =1L;
        private String name;
        public int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.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;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
        ArrayList<Person> list=new ArrayList<>();
        list.add(new Person("张三",18));
        list.add(new Person("李四",19));
        list.add(new Person("王五",20));
        list.add(new Person("赵六",21));
        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day15\\src\\personlist.txt"));
            oos.writeObject(list);
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day15\\src\\personlist.txt"));
            Object obj=ois.readObject();
            ois.close();
            oos.close();
            ArrayList<Person> list2= (ArrayList<Person>)obj;
            for (Person person : list2) {
                System.out.println(person);
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    
发布了113 篇原创文章 · 获赞 1 · 访问量 955

猜你喜欢

转载自blog.csdn.net/weixin_44876003/article/details/103343157