亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

對(duì)象的序列化存儲(chǔ):Serializable 和 Parceable

RyanQ / 1345人閱讀

摘要:而且這種方式也是推薦的序列化方式,因此我們應(yīng)該首選。只要實(shí)現(xiàn)了這個(gè)接口,一個(gè)類的對(duì)象就可以實(shí)現(xiàn)序列化并可以通過和進(jìn)行傳遞了。

文章參考自任玉剛大神的書籍《Android開發(fā)藝術(shù)探索》,強(qiáng)烈推薦這本書。

在進(jìn)行Android開發(fā)的時(shí)候我們有時(shí)候需要用到數(shù)據(jù)的持久化存儲(chǔ),或者在進(jìn)程之間傳遞數(shù)據(jù)。其中就可能需要用到對(duì)象的序列化,經(jīng)過序列化的對(duì)象之后可以通過Intent或者Boundle來傳輸了。接下來還是想些介紹下吧。

1.什么叫序列化,什么叫反序列化

序列化: 將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進(jìn)制串的過程。
反序列化:將在序列化過程中所生成的二進(jìn)制串轉(zhuǎn)換成數(shù)據(jù)結(jié)構(gòu)或者對(duì)象的過程。

簡單來說,序列化就是將我們生成的對(duì)象進(jìn)行存儲(chǔ)起來(比如磁盤上),以用來將來使用或者在網(wǎng)絡(luò)上進(jìn)行傳輸,而反序列化呢,就是由我們的之前序列化生成的二進(jìn)制串重新生成對(duì)象的過程。注意,這里我們反復(fù)說的序列化啦,反序列化啦,都是針對(duì)的對(duì)象,而非。因?yàn)槲覀兪轻槍?duì)對(duì)象進(jìn)行存取與傳輸?shù)?,而非類,?dāng)我們需要重新獲取之前的對(duì)象的時(shí)候,是直接讀取出來的(從文件或網(wǎng)絡(luò)中),而非根據(jù)類new出一個(gè)對(duì)象,這點(diǎn)是需要注意的。

2.如何序列化

序列話的方式有兩種,一種是實(shí)現(xiàn)Serializable接口,一種是實(shí)現(xiàn)Parceable接口,下面會(huì)具體介紹這兩種方式。

a.實(shí)現(xiàn)Serializable接口

這種序列化方式是Java提供的,它的優(yōu)點(diǎn)是簡單,其實(shí)Serializable接口是個(gè)空接口,因而我們并不需要實(shí)現(xiàn)什么抽象方法,但是我們卻往往需要在類中聲明一個(gè)靜態(tài)變量標(biāo)識(shí)(serialVersionUID),但這不是必須的,我們不聲明,依然可以實(shí)現(xiàn)序列化,但是這樣的話會(huì)對(duì)反序列化產(chǎn)生一定的影響,可能會(huì)在我們對(duì)類做了修改之后而造成對(duì)象的反序列化失敗。聲明方式如下:

private static final long serialVersionUID = 8711368828010083044L;

注意,這里的值可以是任意值。

下面我們來具體實(shí)現(xiàn)下。

package com.qc.admin.myserializableparceabledemo;

import java.io.Serializable;

/**
 * Created by admin on 2016/12/1.
 */

public class User implements Serializable {

    private static final long serialVersionUID = 519067123721295773L;

    public int userId;
    public String userName;
    public boolean isMale;

    public User(int userId, String userName, boolean isMale) {

        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;

    }

    @Override
    public String toString() {
        return "User{ " +
                "userId = " + userId +
                ", userName = " + userName +
                ", isMale = " + isMale +
                " }";
    }
}

下面是序列化與反序列化過程:

    private void beginSerizable() throws IOException, ClassNotFoundException {

        // 序列化
        User user = new User(2016, "qian", true);
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File(getFilesDir(), "myfile.txt")));
        out.writeObject(user);
        out.close();

        // 反序列化
        // 注意,這里后面的“/myfile.txt”前面有個(gè)斜杠“/”,否則會(huì)報(bào)“FileNotFoundException”異常
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(getFilesDir() + "/myfile.txt"));
        User mUser = (User) in.readObject();
        textView.setText(mUser.toString());
        in.close();
        Log.i("test",mUser.toString());
    }

運(yùn)行結(jié)果截圖:

注意:如果是在Android項(xiàng)目中調(diào)用以上方法,別忘了在Manifest.xml文件中配置如下權(quán)限:

    
    
b.實(shí)現(xiàn)Parceable接口

這種方式是Android提供的方式,相比較前面那種方式來講,這種方式稍微有點(diǎn)復(fù)雜,我們需要自己盡享序列化與反序列化的操作,但是它卻更加高效,并不需要執(zhí)行大量的I/O操作。而且這種方式也是Android推薦的序列化方式,因此我們應(yīng)該首選Parceable。只要實(shí)現(xiàn)了這個(gè)接口,一個(gè)類的對(duì)象就可以實(shí)現(xiàn)序列化并可以通過Intent和Binder進(jìn)行傳遞了。下面請(qǐng)看實(shí)例:

public class Book implements Parcelable {
    public String bookTitle;
    public int bookId;

    protected Book(Parcel in) {
        bookTitle = in.readString();
        bookId = in.readInt();
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(bookTitle);
        parcel.writeInt(bookId);
    }
}

這里將Book這個(gè)類就實(shí)現(xiàn)了Parcelable接口,其實(shí)在Android Studio IDE中,上述過程很簡單,我們只需要定義一個(gè)類,實(shí)現(xiàn)Parcelable接口,然后在里面定義我們的屬性或者說是字段,根據(jù)提示的錯(cuò)誤,按照它提示的方法覆蓋相應(yīng)的方法,之后的一切其實(shí)都可以自動(dòng)生成(不過如果需要構(gòu)造方法的話,那就需要自動(dòng)生成了,toString()方法也是自己實(shí)現(xiàn)的),所以不用擔(dān)心在Android開發(fā)中通過實(shí)現(xiàn)Parceable接口會(huì)比較麻煩,因?yàn)锳S都會(huì)為你自動(dòng)生成。
上面我們已經(jīng)完整的將Book類實(shí)現(xiàn)了Parceable接口,那接下來如何序列化和反序列化呢?如果你說,剛才不是已經(jīng)說過了嗎,采用文件讀取的方式不久可以了啦...當(dāng)你那樣做的時(shí)候,你會(huì)發(fā)現(xiàn)會(huì)報(bào)如下的錯(cuò)誤:

Why???...什么情況?提示我們Book類沒有實(shí)現(xiàn)序列化:

/System.err: java.io.NotSerializableException: com.qc.admin.myserializableparceabledemo.Book

好啦,之所以出現(xiàn)這種問題,并不是我們的實(shí)現(xiàn)過程有問題,而是使用該類的方式行不通。到這里我們就明白了Serializable和Parceable兩種方式實(shí)現(xiàn)序列化還是有區(qū)別的,剛才我們也講了,Parceable更加高效,不會(huì)像Serializable那樣有大量的I/O操作,這句話的具體含義就道出了Serializable與Parcelable區(qū)別:雖然兩者都是用于支持序列化、反序列化話操作,但是兩者最大的區(qū)別在于存儲(chǔ)媒介的不同,Serializable是將序列化后的對(duì)象存儲(chǔ)在硬盤上,使用I/O讀寫的方式,而Parcelable是將其存儲(chǔ)在內(nèi)存中,是針對(duì)內(nèi)存的讀寫,熟悉計(jì)算機(jī)組成原理的朋友都知道,內(nèi)存的讀寫速度顯然要遠(yuǎn)遠(yuǎn)大于I/O的讀寫速度,這也是為什么Android中推薦使用Parcelable這種方式來實(shí)現(xiàn)對(duì)象的序列化。
那我們應(yīng)該怎么使用通過實(shí)現(xiàn)Parcelable接口實(shí)現(xiàn)序列化的對(duì)象呢?答案是:通過Intent方式傳遞,除了基本類型外,Intent只能傳輸序列化之后的對(duì)象,對(duì)應(yīng)這兩種序列化方式,也有兩種相應(yīng)的方法:

        mIntent.getSerializableExtra(string name );
        mIntent.getParcelableExtra(String name );

當(dāng)然,放入的操作就沒有這種區(qū)分了,都是方法:

mIntent.putExtra();

我們可以在第一個(gè)Activity中將序列化對(duì)象放入Intent,在另一個(gè)Activity中取出,比如:
在另一端獲取對(duì)象,例如:

        Bundle mBundle = getIntent().getExtras();
        Book mBook = mBundle.getParcelable("book1");

下面再看類User實(shí)現(xiàn)Parceable接口的過程,它內(nèi)部包含了一個(gè)可序列化的類Book,具體細(xì)節(jié)跟上面的有點(diǎn)不同:

package com.qc.admin.myserializableparceabledemo;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by admin on 2016/12/1.
 */

public class User implements Parcelable {

    public int userId;
    public String userName;
    public boolean isMale;
    public Book book;


    public User(int userId, String userName, boolean isMale, Book book) {

        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;
        this.book = book;
    }


    protected User(Parcel in) {
        userId = in.readInt();
        userName = in.readString();
        isMale = in.readByte() != 0;
        // 此為不同之處1
        // 也可以通過這種方式:book = in.readParcelable(Thread.currentThread().getContextClassLoader());
        book = in.readParcelable(Book.class.getClassLoader());
        
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };


    // 幾乎在所有的情況下都應(yīng)該返回0,只有在當(dāng)前對(duì)象中存在文件描述的時(shí)候,此方法返回CONTENTS_FILE_DESCRIPTOR(常量值為1)
    @Override
    public int describeContents() {
        return 0;
    }

    // 將對(duì)象寫入序列化結(jié)構(gòu)中,其中i標(biāo)識(shí)有兩種值,0或者1(PARCELABLE_WRITE_RETURN_VALUE)
    // 為1時(shí)表示當(dāng)前對(duì)象需要作為返回值返回,不能立即釋放資源,幾乎所有情況都為0
    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(userId);
        parcel.writeString(userName);
        // 注意這里,并不是直接寫入boolean值,而是寫入整數(shù)值
        parcel.writeByte((byte) (isMale ? 1 : 0));
        // 此為不同之處2
        parcel.writeParcelable(book, i);
    }

    @Override
    public String toString() {
        return "User{ " +
                "userId = " + userId +
                ", userName = " + userName +
                ", isMale = " + isMale +
                "book = " + book.toString() +
                " }";
    }

}

可以看出,結(jié)果已經(jīng)正確的打印了出來了:

注意:在 Parcelable 中,我們無法直接寫入 boolean 值,而是將其轉(zhuǎn)化為整數(shù)值進(jìn)行保存,這里為 Byte,當(dāng)然,你也可以使用 Int 等。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/66307.html

相關(guān)文章

  • JAVA 列化

    摘要:靜態(tài)變量序列化情境查看清單的代碼。之所以打印的原因在于序列化時(shí),并不保存靜態(tài)變量,這其實(shí)比較容易理解,序列化保存的是對(duì)象的狀態(tài),靜態(tài)變量屬于類的狀態(tài),因此序列化并不保存靜態(tài)變量。解決要想將父類對(duì)象也序列化,就需要讓父類也實(shí)現(xiàn)接口。 原文 https://www.ibm.com/developer...  引言 將 Java 對(duì)象序列化為二進(jìn)制文件的 Java 序列化技術(shù)是 Java 系...

    GeekQiaQia 評(píng)論0 收藏0
  • Java列化

    摘要:的序列化是將一個(gè)對(duì)象表示成字節(jié)序列,該字節(jié)序列包括了對(duì)象的數(shù)據(jù),有關(guān)對(duì)象的類型信息和存儲(chǔ)在對(duì)象中的數(shù)據(jù)類型。任何實(shí)現(xiàn)了接口的類都可以被序列化。一旦對(duì)象被序列化或者重新裝配,就會(huì)分別調(diào)用那兩個(gè)方法。 Java序列化 1. 什么是序列化? 序列化是將一個(gè)對(duì)象的狀態(tài),各屬性的值序列化保存起來,然后在合適的時(shí)候通過反序列化獲得。 Java的序列化是將一個(gè)對(duì)象表示成字節(jié)序列,該字節(jié)序列包括了對(duì)象...

    lbool 評(píng)論0 收藏0
  • 淺談Java列化

    摘要:的序列化是將一個(gè)對(duì)象表示成字節(jié)序列,該字節(jié)序列包括了對(duì)象的數(shù)據(jù),有關(guān)對(duì)象的類型信息和存儲(chǔ)在對(duì)象中的數(shù)據(jù)類型。這個(gè)是根據(jù)類名接口名成員方法及屬性等來生成一個(gè)位的哈希字段,因?yàn)樵黾恿俗侄危虼松傻牟灰粯恿恕? Java序列化 什么是序列化? 序列化是將一個(gè)對(duì)象的狀態(tài),各屬性的值序列化保存起來,然后在合適的時(shí)候通過反序列化獲得。 Java的序列化是將一個(gè)對(duì)象表示成字節(jié)序列,該字節(jié)序列包括了對(duì)...

    winterdawn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<