<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-128  評論-55  文章-5  trackbacks-0
    1. 什么是Serialization?

    串行化(Serialization)是計算機科學中的一個概念,它是指將對象存儲到介質(如文件、內在緩沖區等)中或是以二進制方式通過網絡傳輸。之后可以通過反串行化從這些連續的位數據重新構建一個與原始對象狀態相同的對象,因此在特定情況下也可以說是得到一個副本,但并不是所有情況都這樣。

    Java有Serialization API為開發者提供了一種標準的機制來串行化類。

    2. 為什么要Serilzation?

    特別地,串行化主要有三種用途:
    1)作為一種持久化機制
        如果使用的是FileOutputStream流的方式,則數據將被自動地寫入文件中,
    2)作為一種復制機制
        如果使用的是ByteArrayOutputStream流的方式,數據將寫入內存中的字節數組中。該字節數組可以用來創建初始對象的副本,
    3)作為一種通信機制
        如果是使用套接字(Socket)流的方式,則數據自動地通過網絡連接傳輸一另一個端點,并由這個端點上的程序來決定做什么。

    3. Serialization的基本用法默認機制

    將要串行化的類必須實現java.io.Serializable接口,或者是繼承實現了該接口的類。然后通過java.io.ObjectOutputStream類來實現持久化,如果用保存到文件上還需要用到java.io.FileOutputStream類。因為ObjectOutputStream被認為是java.io包中的高級類所以可用它來包裝低級的類FileOutputStream。在持久化過程中調用的一個方法是ObjectOutputStream對象的writeObject(obj)方法。

    當要從文件中恢復對象時,則是使用java.io.OjbectInputStream與FileInputStream類,調用一方法是ObjectInputStream對象的readObject()方法。

    示例1:

    import java.io.*;

    public class Cat implements Serializable {
        private String name;
        public Cat () {
            this.name = "new cat";
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }


    import java.io.*;

    public class CatDemo {
        public static void main(String[] args) {
            Cat cat = new Cat();
            try { //串行化
                FileOutputStream fos = new FileOutputStream("catDemo.out");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                System.out.println(" 1> " + cat.getName());
                cat.setName("My Cat");   
            oos.writeObject(cat);
                oos.close();         
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            try { //反串行化
                FileInputStream fis = new FileInputStream("catDemo.out");
                ObjectInputStream ois = new ObjectInputStream(fis);

                cat = (Cat) ois.readObject();
               
                System.out.println(" 2> " + cat.getName());
                ois.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }catch(ClassNotFoundException ex) {    
            ex.printStackTrace();
        }

        }
    }



    4. Serialization常見問題

    正如前面提到的,所有可串行化的類必須直接或是通過繼承方式間接地實現java.io.Serializable接口,由于Object類關沒有實現這個接口,所以并不是所有類的對象都是可串行化的。像AWT與Swing的GUI組件、字符串、數組等都是可串行化的,而像一些系統級的類(Thread,OutputStream 等)和Socket類是不可串行化的。

    問題一:如果在一個可串行化的類中Has-As不可串行化的類該怎么處理?
    在這種情況下在運行時會拋出NotSerializableException

    為了解決類似問題,Java中提供了transient關鍵字來跳過對不可串行化類的對象的處理。但這依然可能會引起一些問題,在反串行化時,被標識為transient變量不會恢復到其原始狀態,而是提供默認值,如示例2中的pig引用將賦值為null,age變量賦值為0;

    附:基本類型和引用類型的默認值
    對象引用:null
    byte, short, int, long :0
    float, double:0.0
    boolean:false
    char:'\u0000'(這是Unicode字符集的空格)


    示例2:
    import java.io.*;
    public class NewPig2 implements Serializable {
        private String newName;
        private transient Pig pig = new Pig();
        private transient int age = 2;  
        public NewPig2() {
            newName = "new Pig 2";
            //pig = new Pig();
        }
        public Pig getPig() {
            return this.pig;
        }
        public void setName(String name) {
            this.newName = name;
        }
        public String getName() {
            return this.newName;
        }
        public int getAge() {
            return this.age;
        }
    }

    問題二:如果父類不可串行化,子類實現了Serializable會怎樣?
    如果有一個Animal類是不可串行化的,而有一個Dog類繼承自Animal類并且實現了Serializabl接口,則沒有串行化時沒有任何問題,但是在反串行化時將會重新調用Animal的構造函數,如示例3所示。

    示例3的運行結果如下:

    1> No Color - new Dog
    2> Green - My Dog
    4> No Color - My Dog
    因為Animal不可串行化,所以必須運行構造函數,但不會在實現Serializable的反串行化類上運行構造函數。

    示例3:

    public class Animal {
        private String color;
        public Animal () {
            this.color = "No Color";
        }

        public void setColor(String color) {
            this.color = color;
        }
        public String getColor () {
            return this.color;
        }
    }


    import java.io.*;
    public class Dog extends Animal implements Serializable {
        private String name;
        public Dog () {
            this.name = "new Dog";
        }
        public String getName() {
            return this.name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }

    import java.io.*;
    public class DogTest {
        public static void main(String[] args) {
            Dog dog = new Dog();  
            System.out.println(" 1> " + dog.getColor() + " - " + dog.getName());
            dog.setColor("Green");
            dog.setName("My Dog");
            System.out.println(" 2> " + dog.getColor() + " - " + dog.getName());
            try {//串行化
                FileOutputStream fos = new FileOutputStream("myDog.out");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(dog);
                oos.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            try {//反串行化
                FileInputStream fis = new FileInputStream("myDog.out");
                ObjectInputStream ois = new ObjectInputStream(fis);
                dog = (Dog) ois.readObject();       
                System.out.println(" 4> " + dog.getColor() + " - " + dog.getName());
                ois.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    5.
    自定義默認方法:使用writeOject和readObject

    假如在一個可以串行化的類中有一個不可串行化的對象,但又想保存該對象的狀態信息該如何是好?在這樣情況下可以在這個可串行化的類中實現writeObject()和readObject()。

    示例4:
    import java.io.*;
    import java.util.Scanner;

    public class NewPig3 implements Serializable {
        private String newName;
        private transient Pig pig = new Pig();
        private transient int age = 2;
       
        public NewPig3() {
            newName = "new Pig 3";
            //pig = new Pig();
        }

        private void writeObject(ObjectOutputStream oos) throws IOException {
            oos.defaultWriteObject();
            oos.writeChars(pig.getName());
        //oos.writeInt(this.age);
        }

        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
            ois.defaultReadObject();
            pig = new Pig();
            Scanner in = new Scanner(ois);
            if (in.hasNextLine()) {   
                pig.setName(in.nextLine());
            }
        }

        public Pig getPig() {
            return this.pig;
        }

        public void setName(String name) {
            this.newName = name;
        }

        public String getName() {
            return this.newName;
        }

        public int getAge() {
            return this.age;
        }
    }


    Author: orangelizq
    email: orangelizq@163.com

    歡迎大家訪問我的個人網站 萌萌的IT人
    posted on 2008-09-05 11:26 桔子汁 閱讀(763) 評論(0)  編輯  收藏 所屬分類: J2SE
    主站蜘蛛池模板: 久久久久亚洲精品天堂| 免费夜色污私人影院在线观看| 久久九九亚洲精品| 中文字幕无线码中文字幕免费| 亚洲欧洲自拍拍偷精品 美利坚| 青青草97国产精品免费观看| vvvv99日韩精品亚洲| 理论片在线观看免费| 国产精品亚洲mnbav网站| 国产成人无码免费网站| 国内精品99亚洲免费高清| 99re6在线精品免费观看| 久久亚洲AV无码精品色午夜麻| 日韩精品无码免费专区午夜| 亚洲成AV人片在WWW色猫咪| 久久久久久久久久国产精品免费| 亚洲男人的天堂在线播放| 亚洲免费在线视频观看| 亚洲色欲色欱wwW在线| 波多野结衣一区二区免费视频| 国产亚洲情侣久久精品| 亚洲精品国产精品乱码不99 | 久久精品免费一区二区喷潮| 亚洲色中文字幕在线播放| 免费成人av电影| 日韩免费电影网站| 日韩亚洲人成在线| 亚洲精品NV久久久久久久久久| a级毛片免费全部播放| 亚洲精品国产免费| 国产精品另类激情久久久免费| 久久国产精品免费| 亚洲丝袜中文字幕| 免费国产精品视频| 久久国产精品免费专区| 亚洲另类无码专区丝袜| 亚洲人JIZZ日本人| 成人毛片免费视频| 久久国产免费一区二区三区| 亚洲熟妇无码AV| 亚洲AV日韩AV永久无码久久 |