序列化流和反序列化流

序列化流和反序列化流的概述


image.png
序列化流 ObjectOutputStream類

使用步驟:
1.創(chuàng)建ObjectOutputStream對象,構造方法中傳遞字節(jié)輸出流
2.使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中
3.釋放資源

/*
    java.io.ObjectOutputStream extends OutputStream
    ObjectOutputStream:對象的序列化流
    作用:把對象以流的方式寫入到文件中保存

    構造方法:
        ObjectOutputStream(OutputStream out) 創(chuàng)建寫入指定 OutputStream 的 ObjectOutputStream。
        參數(shù):
            OutputStream out:字節(jié)輸出流
    特有的成員方法:
        void writeObject(Object obj) 將指定的對象寫入 ObjectOutputStream。

    使用步驟:
        1.創(chuàng)建ObjectOutputStream對象,構造方法中傳遞字節(jié)輸出流
        2.使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中
        3.釋放資源
 */
public class Demo01ObjectOutputStream {
    public static void main(String[] args) throws IOException {
        //1.創(chuàng)建ObjectOutputStream對象,構造方法中傳遞字節(jié)輸出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("10_IO\\person.txt"));
        //2.使用ObjectOutputStream對象中的方法writeObject,把對象寫入到文件中
        oos.writeObject(new Person("小美女",18));
        //3.釋放資源
        oos.close();
    }
}

必須給相應類標記,如果沒有標記。就會拋出NotSerializableException沒有序列化異常


image.png
/*
    序列化和反序列化的時候,會拋出NotSerializableException沒有序列化異常
    類通過實現(xiàn) java.io.Serializable 接口以啟用其序列化功能。未實現(xiàn)此接口的類將無法使其任何狀態(tài)序列化或反序列化。
    Serializable接口也叫標記型接口
        要進行序列化和反序列化的類必須實現(xiàn)Serializable接口,就會給類添加一個標記
        當我們進行序列化和反序列化的時候,就會檢測類上是否有這個標記
            有:就可以序列化和反序列化
            沒有:就會拋出 NotSerializableException異常
    去市場買肉-->肉上有一個藍色章(檢測合格)-->放心購買-->買回來怎么吃隨意

    static關鍵字:靜態(tài)關鍵字
        靜態(tài)優(yōu)先于非靜態(tài)加載到內存中(靜態(tài)優(yōu)先于對象進入到內存中)
        被static修飾的成員變量不能被序列化的,序列化的都是對象
        private static int age;
        oos.writeObject(new Person("小美女",18));
        Object o = ois.readObject();
        Person{name='小美女', age=0}
    transient關鍵字:瞬態(tài)關鍵字
        被transient修飾成員變量,不能被序列化
        private transient int age;
        oos.writeObject(new Person("小美女",18));
        Object o = ois.readObject();
        Person{name='小美女', age=0}
 */
public class Person implements Serializable{
    private static final long serialVersionUID = 1L;
    private String name;
    //private static int age;
    //private transient int age;
    public int age;    
    public Person() {
    }
    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類

使用步驟:
1.創(chuàng)建ObjectInputStream對象,構造方法中傳遞字節(jié)輸入流
2.使用ObjectInputStream對象中的方法readObject讀取保存對象的文件
3.釋放資源
4.使用讀取出來的對象(打印)
readObject方法聲明拋出了ClassNotFoundException(class文件找不到異常)
當不存在對象的class文件時拋出此異常
反序列化的前提:
1.類必須實現(xiàn)Serializable
2.必須存在類對應的class文件

/*
    java.io.ObjectInputStream extends InputStream
    ObjectInputStream:對象的反序列化流
    作用:把文件中保存的對象,以流的方式讀取出來使用
    構造方法:
        ObjectInputStream(InputStream in) 創(chuàng)建從指定 InputStream 讀取的 ObjectInputStream。
        參數(shù):
            InputStream in:字節(jié)輸入流
    特有的成員方法:
        Object readObject() 從 ObjectInputStream 讀取對象。

    使用步驟:
        1.創(chuàng)建ObjectInputStream對象,構造方法中傳遞字節(jié)輸入流
        2.使用ObjectInputStream對象中的方法readObject讀取保存對象的文件
        3.釋放資源
        4.使用讀取出來的對象(打印)

     readObject方法聲明拋出了ClassNotFoundException(class文件找不到異常)
     當不存在對象的class文件時拋出此異常
     反序列化的前提:
        1.類必須實現(xiàn)Serializable
        2.必須存在類對應的class文件
 */
public class Demo02ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.創(chuàng)建ObjectInputStream對象,構造方法中傳遞字節(jié)輸入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("10_IO\\person.txt"));
        //2.使用ObjectInputStream對象中的方法readObject讀取保存對象的文件
        Object o = ois.readObject();
        //3.釋放資源
        ois.close();
        //4.使用讀取出來的對象(打印)
        System.out.println(o);
        Person p = (Person)o;
        System.out.println(p.getName()+p.getAge());
    }
}

static關鍵字:靜態(tài)關鍵字
靜態(tài)優(yōu)先于非靜態(tài)加載到內存中(靜態(tài)優(yōu)先于對象進入到內存中)
被static修飾的成員變量不能被序列化的,序列化的都是對象
private static int age;
oos.writeObject(new Person("小美女",18));
Object o = ois.readObject();
Person{name='小美女', age=0}
transient關鍵字:瞬態(tài)關鍵字
被transient修飾成員變量,不能被序列化
private transient int age;
oos.writeObject(new Person("小美女",18));
Object o = ois.readObject();
Person{name='小美女', age=0}

序列號沖突異常的原理和解決方案(InvalidClassException 異常)

image.png
解決方案:

無論是否對類的定義進行修改,都不能重新生成新的序列號
可以手動給類添加一個序列號


image.png

練習:序列化集合

  1. 將存有多個自定義對象的集合序列化操作,保存到 list.txt 文件中。
  2. 反序列化 list.txt ,并遍歷集合,打印對象信息。
/*
    練習:序列化集合
        當我們想在文件中保存多個對象的時候
        可以把多個對象存儲到一個集合中
        對集合進序列化和反序列化
    分析:
        1.定義一個存儲Person對象的ArrayList集合
        2.往ArrayList集合中存儲Person對象
        3.創(chuàng)建一個序列化流ObjectOutputStream對象
        4.使用ObjectOutputStream對象中的方法writeObject,對集合進行序列化
        5.創(chuàng)建一個反序列化ObjectInputStream對象
        6.使用ObjectInputStream對象中的方法readObject讀取文件中保存的集合
        7.把Object類型的集合轉換為ArrayList類型
        8.遍歷ArrayList集合
        9.釋放資源
 */
public class Demo03Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.定義一個存儲Person對象的ArrayList集合
        ArrayList<Person> list = new ArrayList<>();
        //2.往ArrayList集合中存儲Person對象
        list.add(new Person("張三",18));
        list.add(new Person("李四",19));
        list.add(new Person("王五",20));
        //3.創(chuàng)建一個序列化流ObjectOutputStream對象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("10_IO\\list.txt"));
        //4.使用ObjectOutputStream對象中的方法writeObject,對集合進行序列化
        oos.writeObject(list);
        //5.創(chuàng)建一個反序列化ObjectInputStream對象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("10_IO\\list.txt"));
        //6.使用ObjectInputStream對象中的方法readObject讀取文件中保存的集合
        Object o = ois.readObject();
        //7.把Object類型的集合轉換為ArrayList類型
        ArrayList<Person> list2 = (ArrayList<Person>)o;
        //8.遍歷ArrayList集合
        for (Person p : list2) {
            System.out.println(p);
        }
        //9.釋放資源
        ois.close();
        oos.close();
    }
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容