<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)是計算機科學中的一個概念,它是指將對象存儲到介質(zhì)(如文件、內(nèi)在緩沖區(qū)等)中或是以二進制方式通過網(wǎng)絡傳輸。之后可以通過反串行化從這些連續(xù)的位數(shù)據(jù)重新構建一個與原始對象狀態(tài)相同的對象,因此在特定情況下也可以說是得到一個副本,但并不是所有情況都這樣。

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

    2. 為什么要Serilzation?

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

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

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

    當要從文件中恢復對象時,則是使用java.io.OjbectInputStream與FileInputStream類,調(diào)用一方法是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常見問題

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

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

    為了解決類似問題,Java中提供了transient關鍵字來跳過對不可串行化類的對象的處理。但這依然可能會引起一些問題,在反串行化時,被標識為transient變量不會恢復到其原始狀態(tài),而是提供默認值,如示例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;
        }
    }

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

    示例3的運行結果如下:

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

    示例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

    假如在一個可以串行化的類中有一個不可串行化的對象,但又想保存該對象的狀態(tài)信息該如何是好?在這樣情況下可以在這個可串行化的類中實現(xiàn)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

    歡迎大家訪問我的個人網(wǎng)站 萌萌的IT人
    posted on 2008-09-05 11:26 桔子汁 閱讀(763) 評論(0)  編輯  收藏 所屬分類: J2SE
    主站蜘蛛池模板: 亚洲深深色噜噜狠狠爱网站| 国产精品无码免费视频二三区 | 偷自拍亚洲视频在线观看| 野花高清在线电影观看免费视频 | 成人精品综合免费视频| 亚洲美日韩Av中文字幕无码久久久妻妇| 亚洲丁香婷婷综合久久| 成人伊人亚洲人综合网站222| 高清免费久久午夜精品| 亚洲女初尝黑人巨高清| 亚洲电影免费在线观看| 亚洲国产情侣一区二区三区| 免费人成在线视频| 亚洲国产成人精品无码区花野真一| 国产高清免费在线| 日韩大片在线永久免费观看网站| 国产亚洲精品AA片在线观看不加载| 国产一区二区三区免费观在线| 久久国产亚洲观看| 1000部拍拍拍18勿入免费视频软件| 亚洲a级在线观看| 国产成人免费手机在线观看视频| eeuss影院免费92242部| 亚洲激情在线视频| 免费观看AV片在线播放| 黄床大片30分钟免费看| 久久精品国产亚洲av四虎| 99在线精品视频观看免费| 国产精品亚洲综合| 亚洲精品国产字幕久久不卡| 国产四虎免费精品视频| 美女的胸又黄又www网站免费| 亚洲精品午夜无码专区| 歪歪漫画在线观看官网免费阅读 | 免费人成视网站在线观看不卡| 国产无遮挡色视频免费观看性色| 亚洲第一页在线播放| 亚洲精品成人在线| 97视频免费在线| 中文字幕在线观看免费| 亚洲第一男人天堂|