序列化

序列化

計(jì)算機(jī)中最原始的數(shù)據(jù)就是0和1,有電才能驅(qū)動(dòng)計(jì)算機(jī)運(yùn)行,1和0對(duì)應(yīng)電的正負(fù)暂氯,易經(jīng)有太極生兩儀,兩儀生四象存筏,四象生八卦,八卦衍萬物味榛,所以0和1可衍生萬物椭坚,萬物皆對(duì)象,那這對(duì)象怎么保存搏色,最簡(jiǎn)單就是保存0和1就行善茎,對(duì)象轉(zhuǎn)變成0和1就是序列化,0和1轉(zhuǎn)成對(duì)象就是反序列化

存儲(chǔ)數(shù)據(jù)傳輸數(shù)據(jù)

簡(jiǎn)單舉的例子:

存儲(chǔ):在java中的面向?qū)ο缶幊讨衅到危瑪?shù)據(jù)通常是用一個(gè)字段表示垂涯,如名字name=張三,字段為name,value為張三略吨,這個(gè)字段在一個(gè)類對(duì)象中集币,這個(gè)對(duì)象是在程序運(yùn)行中創(chuàng)建在內(nèi)存中的考阱,持久保存"張三"就需要把這個(gè)對(duì)象序列化保存在硬盤上翠忠。

傳輸:傳輸和存儲(chǔ)是一樣的,上面說的存儲(chǔ)就是內(nèi)存?zhèn)饔脖P乞榨,另一種場(chǎng)景秽之,兩臺(tái)計(jì)算機(jī)之間傳輸數(shù)據(jù),序列化后的數(shù)據(jù)是0和1的2進(jìn)制串吃既,比如兩臺(tái)計(jì)算機(jī)連著一根金屬線考榨,在這跟金屬線上通電與斷電表示1或0,這樣另一臺(tái)計(jì)算機(jī)得到2進(jìn)制串后進(jìn)行反序列化鹦倚,就可以得到內(nèi)容相同的對(duì)象了河质。

序列化故名思意就是按序排列變化,"序"就是某種協(xié)議,按這種協(xié)議排列變成另一種形態(tài)

簡(jiǎn)單的概括

  • 序列化: 主要用于網(wǎng)絡(luò)傳輸掀鹅,數(shù)據(jù)持久化散休,一般序列化也稱為編碼(Encode)
  • 反序列化: 主要用于從網(wǎng)絡(luò),磁盤上讀取字節(jié)數(shù)組還原成原始對(duì)象乐尊,一般反序列化也稱為解碼(Decode)

以上得知序列化是將一個(gè)對(duì)象的數(shù)據(jù)保存或傳輸戚丸,怎么樣使這個(gè)對(duì)象能被序列化?

Serializable:可序列化的

Serializable是一個(gè)空接口扔嵌,中文意思使可序列化的限府,意思使實(shí)現(xiàn)了這個(gè)接口的javaBean類可以序列化成2進(jìn)制串,使用ObjectOutputStream 序列化痢缎,ObjectInputStream 反序列化胁勺。

public class SPerson implements Serializable {
//serialVersionUID 是 Java 為每個(gè)序列化類產(chǎn)生的版本標(biāo)識(shí),可用來保證在反序列時(shí)独旷,發(fā)送方發(fā)送的和接受方接收的是可兼容的對(duì)象姻几。如果接收方接收的類的 //serialVersionUID 與發(fā)送方發(fā)送的 serialVersionUID 不一致,進(jìn)行反序列時(shí)會(huì)拋出 InvalidClassException
    //
    private static final long serialVersionUID = 2088008379212083287L;
    private String name;
    private int age;
}
public class SerializeableTest {
    public static void main(String[] args){
        SPerson sPerson1 =new SPerson();
        sPerson1.setName("張三");
        sPerson1.setAge(18);
        System.out.println("serializable="+ sPerson1.getName()+"--"+ sPerson1.getAge());
        try {
            ByteArrayOutputStream baos=new ByteArrayOutputStream();
            ObjectOutputStream oos=new ObjectOutputStream(baos);
            oos.writeObject(sPerson1);
            byte[] bs2=  baos.toByteArray();
            System.out.println("serializable序列化后="+ Arrays.toString(bs2));
            ObjectInputStream ojis=new ObjectInputStream(new ByteArrayInputStream(bs2));
            SPerson sPerson2 = (SPerson) ojis.readObject();
            System.out.println("serializable反序列化="+ sPerson2.getName()+"--"+ sPerson2.getAge());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

打印結(jié)果:

serializable=張三--18
serializable序列化后=[-84, -19, 0, 5, 115, 114, 0, 39, 99, 111, 109, 46, 100, 98, 102, 46, 106, 97, 118, 97, 115, 116, 117, 100, 121, 46, 115, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 46, 83, 80, 101, 114, 115, 111, 110, 28, -6, 24, -114, -30, -7, -80, 87, 2, 0, 2, 73, 0, 3, 97, 103, 101, 76, 0, 4, 110, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 120, 112, 0, 0, 0, 18, 116, 0, 6, -27, -68, -96, -28, -72, -119]
serializable反序列化=張三--18

序列化后的文件直接用sublime打開如下

aced 0005 7372 002e 636f 6d2e 7a65 726f
2e73 6572 6961 6c69 7a61 626c 6564 656d
6f2e 7365 7269 616c 697a 6162 6c65 2e53
7475 6465 6e74 e2d9 8cd7 833d f19e 0200
...
  • AC ED: STREAM_MAGIC. 聲明使用了序列化協(xié)議.
  • 00 05: STREAM_VERSION. 序列化協(xié)議版本.
  • 0x73: TC_OBJECT. 聲明這是一個(gè)新的對(duì)象.
  • 0x72: TC_CLASSDESC. 聲明這里開始一個(gè)新Class势告。
  • 00 2e: Class名字的長度.

不容易發(fā)現(xiàn)的問題:

  SPerson sPerson1 =new SPerson();
        sPerson1.setName("張三");
        sPerson1.setAge(18);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(sPerson1);
sPerson1.setName("李四");
//oos.writeUnshared(sPerson1);不共享
oos.writeObject(sPerson1);共享
  ObjectInputStream ojis=new ObjectInputStream(new ByteArrayInputStream(bs2));
            SPerson sPerson2 = (SPerson) ojis.readObject();
            SPerson sPerson3 = (SPerson) ojis.readObject();
//以上是想保存一個(gè)李四18蛇捌,設(shè)置李四后調(diào)用oos.writeObject(sPerson1) 反序列化出來的是兩個(gè)張三,得用oos.writeUnshared(sPerson1)咱台;

Parcelable 可打包的

Parcelable是Android為我們提供的序列化的接口,Parcelable相對(duì)于Serializable的使用相對(duì)復(fù)雜一些,但Parcelable的效率相對(duì)Serializable也高很多,Parcelable vs Serializable 號(hào)稱快10倍的效率

Parcelable是Android SDK提供的络拌,它是基于內(nèi)存的,由于內(nèi)存讀寫速度高于硬盤回溺,因此Android中的跨進(jìn)程對(duì)象的傳遞一般使用Parcelable

public class PPerson implements Parcelable {
    private String name;
    private int age;
//反序列化時(shí)構(gòu)建對(duì)象春贸,序列化的數(shù)據(jù)包在Parcel中,Parcel就是包裹的意思
    protected PPerson(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }
//構(gòu)建器遗遵,構(gòu)造一個(gè)PPerson對(duì)象和PPerson數(shù)組對(duì)象
    public static final Creator<PPerson> CREATOR = new Creator<PPerson>() {
        @Override
        public PPerson createFromParcel(Parcel in) {
            return new PPerson(in);
        }

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

//描述包含在這個(gè) Parcelable 實(shí)例的封送表示中的特殊對(duì)象的種類萍恕。例如,如果對(duì)象將在 {@link writeToParcel(Parcel, int)} 的輸出中包含文件描述符车要,則此方法的返回值必須包含 {@link CONTENTS_FILE_DESCRIPTOR} 位允粤。 @return 一個(gè)位掩碼,指示由此 Parcelable 對(duì)象實(shí)例編組的一組特殊對(duì)象類型翼岁。
    @Override
    public int describeContents() {
        return 0;
    }
//將數(shù)據(jù)打包到Parcel
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }

}

Android也是基于linux类垫,進(jìn)程之間內(nèi)存不共享,因此進(jìn)程之間的信息傳遞需要序列化與反序列化琅坡,通常在四大組件之間傳遞對(duì)象需要將對(duì)象序列化悉患,啟動(dòng)一個(gè)Activity交給AMS完成,AMS全名ActivityManagerService,是系統(tǒng)服務(wù)榆俺,是另一個(gè)進(jìn)程售躁,這里就得序列化了坞淮,關(guān)于啟動(dòng)四大組件是比較復(fù)雜的流程,可以看看下面的文章

startActivity啟動(dòng)過程分析:http://gityuan.com/2016/03/12/start-activity/

Android中Intent/Bundle的通信原理及大小限制

速度快陪捷,比如兩個(gè)Activity之間傳遞碾盐,Activity用于頁面展示,速度一定得快揩局,其次數(shù)據(jù)量也不能過大毫玖,大數(shù)據(jù)傳輸,肯定會(huì)導(dǎo)致速度變慢凌盯,能感覺頁面明顯切換得慢了付枫,數(shù)據(jù)過大時(shí)會(huì)報(bào)一個(gè)錯(cuò)誤,

Intent 中的 Bundle 是使用 Binder 機(jī)制進(jìn)行數(shù)據(jù)傳送的驰怎。能使用的 Binder 的緩沖區(qū)是有大小限制的(有些手機(jī)是 2 M)阐滩,而一個(gè)進(jìn)程默認(rèn)有 16 個(gè) Binder 線程,所以一個(gè)線程能占用的緩沖區(qū)就更小了( 有人以前做過測(cè)試县忌,大約一個(gè)線程可以占用 128 KB)掂榔。所以當(dāng)你看到 The Binder transaction failed because it was too large 這類 TransactionTooLargeException 異常時(shí),你應(yīng)該知道怎么解決了

怎么實(shí)現(xiàn)跨進(jìn)程通信症杏,通過AIDL快速生成代碼,下面是生成的部分代碼

@Override public void addPerson(com.dbf.studyandtest.myaidl.Person person) throws android.os.RemoteException
{
    //先獲得傳入和傳出的打包對(duì)象Parcel装获,看到obtain應(yīng)該是用了享元模式,與handler傳消息的message一樣厉颤,對(duì)象頻繁使用穴豫,減少new,重復(fù)利用已經(jīng)new好的對(duì)象
  android.os.Parcel _data = android.os.Parcel.obtain();//傳入數(shù)據(jù),就是給另一個(gè)進(jìn)程的數(shù)據(jù)
  android.os.Parcel _reply = android.os.Parcel.obtain();//傳出數(shù)據(jù)逼友,就是另一個(gè)進(jìn)程回傳的數(shù)據(jù)
  try {
    _data.writeInterfaceToken(DESCRIPTOR);
    if ((person!=null)) {
      _data.writeInt(1);
      person.writeToParcel(_data, 0);//將數(shù)據(jù)寫入Parcel精肃,可以看到我們實(shí)現(xiàn)Parcelable的類,調(diào)用的是native方法
    }
    else {
      _data.writeInt(0);
    }
    boolean _status = mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
    if (!_status && getDefaultImpl() != null) {
      getDefaultImpl().addPerson(person);
      return;
    }
    _reply.readException();
    if ((0!=_reply.readInt())) {
      person.readFromParcel(_reply);//從Parcel讀出數(shù)據(jù)帜乞,可以看到我們實(shí)現(xiàn)Parcelable的類司抱,也是調(diào)用native方法
    }
  }
  finally {
      //最后釋放
    _reply.recycle();
    _data.recycle();
  }
}

linux中分用戶空間和內(nèi)核空間,先從用戶空間其中一個(gè)進(jìn)程cp到內(nèi)核空間黎烈,再從內(nèi)核空間映射到用戶空間的另一個(gè)進(jìn)程习柠,想要達(dá)到這個(gè)目的要繼承Binder實(shí)現(xiàn)IInterface,代碼形式都是固定的怨喘,所以有了AIDL,Android Interface Definition Language,即Android接口定義語言

Parcelable與Serializable的性能比較

Serializable性能分析

Serializable是Java中的序列化接口津畸,其使用起來簡(jiǎn)單但開銷較大(因?yàn)镾erializable在序列化過程中使用了反射機(jī)制,故而會(huì)產(chǎn)生大量的臨時(shí)變量必怜,從而導(dǎo)致頻繁的GC),并且在讀寫數(shù)據(jù)過程中后频,它是通過IO流的形式將數(shù)據(jù)寫入到硬盤或者傳輸?shù)骄W(wǎng)絡(luò)上梳庆。

Parcelable性能分析

Parcelable則是以IBinder作為信息載體暖途,在內(nèi)存上開銷比較小,因此在內(nèi)存之間進(jìn)行數(shù)據(jù)傳遞時(shí)膏执,推薦使用Parcelable,而Parcelable對(duì)數(shù)據(jù)進(jìn)行持久化或者網(wǎng)絡(luò)傳輸時(shí)操作復(fù)雜驻售,一般這個(gè)時(shí)候推薦使用Serializable。

性能比較總結(jié)描述

首先Parcelable的性能要強(qiáng)于Serializable的原因我需要簡(jiǎn)單的闡述一下

  • 在內(nèi)存的使用中,前者在性能方面要強(qiáng)于后者
  • 后者在序列化操作的時(shí)候會(huì)產(chǎn)生大量的臨時(shí)變量,(原因是使用了反射機(jī)制)從而導(dǎo)致GC的頻繁調(diào)用,因此在性能上會(huì)稍微遜色
  • Parcelable是以Ibinder作為信息載體的.在內(nèi)存上的開銷比較小,因此在內(nèi)存之間進(jìn)行數(shù)據(jù)傳遞的時(shí)候,Android推薦使用Parcelable,既然是內(nèi)存方面比價(jià)有優(yōu)勢(shì),那么自然就要優(yōu)先選擇.
  • 在讀寫數(shù)據(jù)的時(shí)候,Parcelable是在內(nèi)存中直接進(jìn)行讀寫,而Serializable是通過使用IO流的形式將數(shù)據(jù)讀寫入在硬盤上.
    但是:雖然Parcelable的性能要強(qiáng)于Serializable,但是仍然有特殊的情況需要使用Serializable,而不去使用Parcelable,因?yàn)镻arcelable無法將數(shù)據(jù)進(jìn)行持久化,因此在將數(shù)據(jù)保存在磁盤的時(shí)候,仍然需要使用后者,因?yàn)榍罢邿o法很好的將數(shù)據(jù)進(jìn)行持久化.(原因是在不同的Android版本當(dāng)中,Parcelable可能會(huì)不同,因此數(shù)據(jù)的持久化方面仍然是使用Serializable)

Protobuf

  • 序列化數(shù)據(jù)非常簡(jiǎn)潔更米,緊湊欺栗,與 XML 相比,其序列化之后的數(shù)據(jù)量約為 1/3 到 1/10征峦。
  • 解析速度非吵偌福快,比對(duì)應(yīng)的 XML 快約 20-100 倍栏笆。

一类腮、配置protobuf

插件github地址:https://github.com/google/protobuf-gradle-plugin

1.在項(xiàng)目根目錄的build.gradle中配置:

dependencies {
    classpath 'com.android.tools.build:gradle:4.1.2'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.17'//protobuf插件
}

2.在模塊中的build.gradle中配置:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.protobuf'//protobuf插件
android {
    ...
         sourceSets {
        main {
             java {
            srcDir 'src/main/java'
            }
            proto {
                srcDir 'src/main/proto'//添加protobuf目錄,在里面編寫需要序列化的文件
            }
        }
         }
}

protobuf {
    //配置protoc編譯器
    protoc {
        artifact = 'com.google.protobuf:protoc:3.8.0'//這里的版本跟斜面依賴的版本一致
    }
    //這里配置生成目錄蛉加,編譯后會(huì)在build的目錄下生成對(duì)應(yīng)的java文件
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                remove java
            }
            task.builtins {
                java {}
            }
        }
    }
}
dependencies {
    implementation 'com.google.protobuf:protobuf-java:3.8.0'
}

3.Settings Plugins 搜索安裝 Protobuf Support 插件蚜枢,裝好后可以識(shí)別出.proto文件

二、編寫protobuf

.proto文件編寫 github地址:https://github.com/protocolbuffers/protobuf

proto3本版本java:https://developers.google.com/protocol-buffers/docs/proto3

例子:

syntax = "proto3";//版本 之前有proto2
//package tutorial;
/**java_multiple_files = true
選項(xiàng)可以生成單獨(dú)的.java每個(gè)生成的類的文件
(而不是.java為包裝類生成單個(gè)文件的遺留行為针饥,使用包裝類作為外部類厂抽,并將所有其他類嵌套在包裝類中)。
 */
option java_multiple_files = true;
/** java_package指定生成的類應(yīng)該使用的 Java 包名稱丁眼。
如果您沒有明確指定修肠,它只是匹配package聲明給出的包名,
但這些名稱通常不是合適的 Java 包名(因?yàn)樗鼈兺ǔ2灰杂蛎_頭)户盯。
 */
option java_package = "com.dbf.studyandtest.proto";
/**java_outer_classname選項(xiàng)定義將表示此文件的包裝類的類名嵌施。
如果你不java_outer_classname明確給出a ,它會(huì)通過將文件名轉(zhuǎn)換為大寫駝峰來生成莽鸭。
例如吗伤,默認(rèn)情況下,“my_proto.proto”將使用“MyProto”作為包裝類名稱硫眨。
 */
option java_outer_classname = "_Person";
message Person{
  /**每個(gè)元素上的“= 1”足淆、“= 2”標(biāo)記標(biāo)識(shí)字段在二進(jìn)制編碼中使用的唯一“標(biāo)簽”。
  標(biāo)記數(shù)字 1-15 需要比更高數(shù)字少一個(gè)字節(jié)來編碼礁阁,因此作為一種優(yōu)化巧号,您可以決定將這些標(biāo)記用于常用或重復(fù)的元素,
  而將標(biāo)記 16 和更高的標(biāo)記用于不太常用的可選元素姥闭。重復(fù)字段中的每個(gè)元素都需要重新編碼標(biāo)簽編號(hào)丹鸿,因此重復(fù)字段特別適合這種優(yōu)化。
   */
  //指定字段的類型 定義字段的編號(hào)棚品,在Protocol Buffers中靠欢,字段的編號(hào)非常重要廊敌,字段名僅僅是作為參考和生成代碼用。需要注意的是字段的編號(hào)區(qū)間范圍门怪,其中19000 ~ 19999被Protocol Buffers作為保留字段
  string name = 1;
  int32  age  = 2;

//  message Home{
//    string address = 1;
//  }
//  Home   home = 3;
}

//message Family {
//  Person person = 1;
//}

Make project 一下自動(dòng)生成代碼

/**
 * Protobuf type {@code Person}
 */
public  final class Person extends com.google.protobuf.GeneratedMessageV3 implements PersonOrBuilder {
//省略600多行代碼
}

Serializable對(duì)比

public static void main(String[] args) throws  Exception{
    Person person = Person.newBuilder().setName("張三").setAge(18).build();
    System.out.println("protobuf="+person.getName()+"--"+person.getAge());
    //序列化
    byte[] bs=person.toByteArray();
    System.out.println("protobuf序列化后="+Arrays.toString(bs));
    Person person2=Person.parseFrom(bs);
    System.out.println("protobuf反序列化="+person2.getName()+"--"+person2.getAge());
    System.out.println("\n----------------分割線-------------\n");
    SPerson sPerson1 =new SPerson();
    sPerson1.setName("張三");
    sPerson1.setAge(18);
    System.out.println("serializable="+ sPerson1.getName()+"--"+ sPerson1.getAge());
    try {
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(baos);
        oos.writeObject(sPerson1);
        byte[] bs2=  baos.toByteArray();
        System.out.println("serializable序列化后="+Arrays.toString(bs2));
        ObjectInputStream ojis=new ObjectInputStream(new ByteArrayInputStream(bs2));
        SPerson sPerson2 = (SPerson) ojis.readObject();
        System.out.println("serializable反序列化="+ sPerson2.getName()+"--"+ sPerson2.getAge());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

打印結(jié)果:

protobuf=張三--18
protobuf序列化后=[10, 6, -27, -68, -96, -28, -72, -119, 16, 18]
protobuf反序列化=張三--18

----------------分割線-------------

serializable=張三--18
serializable序列化后=[-84, -19, 0, 5, 115, 114, 0, 39, 99, 111, 109, 46, 100, 98, 102, 46, 106, 97, 118, 97, 115, 116, 117, 100, 121, 46, 115, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 46, 83, 80, 101, 114, 115, 111, 110, 28, -6, 24, -114, -30, -7, -80, 87, 2, 0, 2, 73, 0, 3, 97, 103, 101, 76, 0, 4, 110, 97, 109, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 120, 112, 0, 0, 0, 18, 116, 0, 6, -27, -68, -96, -28, -72, -119]
serializable反序列化=張三--18

.proto Type Notes C++ Type Java/Kotlin Type[1] Python Type[3] Go Type Ruby Type C# Type PHP Type Dart Type
double double double float float64 Float double float double
float float float float float32 Float float float double
int32 使用可變長度編碼骡澈。 編碼負(fù)數(shù)效率低下 - 如果您的字段可能具有負(fù)值,請(qǐng)改用 sint32掷空。 int32 int int int32 Fixnum or Bignum (as required) int integer int
int64 使用可變長度編碼肋殴。 編碼負(fù)數(shù)效率低下 - 如果您的字段可能具有負(fù)值,請(qǐng)改用 sint64坦弟。 int64 long int/long[4] int64 Bignum long integer/string[6] Int64
uint32 使用可變長度編碼护锤。 uint32 int[2] int/long[4] uint32 Fixnum or Bignum (as required) uint integer int
uint64 使用可變長度編碼。 uint64 long[2] int/long[4] uint64 Bignum ulong integer/string[6] Int64
sint32 使用可變長度編碼减拭。 有符號(hào)整數(shù)值蔽豺。 這些比常規(guī) int32 更有效地編碼負(fù)數(shù)。 int32 int int int32 Fixnum or Bignum (as required) int integer int
sint64 使用可變長度編碼拧粪。 有符號(hào)整數(shù)值修陡。 這些比常規(guī) int64 更有效地編碼負(fù)數(shù)。 int64 long int/long[4] int64 Bignum long integer/string[6] Int64
fixed32 總是四個(gè)字節(jié)可霎。 如果值通常大于 228魄鸦,則比 uint32 更有效。 uint32 int[2] int/long[4] uint32 Fixnum or Bignum (as required) uint integer int
fixed64 總是八個(gè)字節(jié)癣朗。 如果值通常大于 256拾因,則比 uint64 更有效。 uint64 long[2] int/long[4] uint64 Bignum ulong integer/string[6] Int64
sfixed32 總是四個(gè)字節(jié)旷余。 int32 int int int32 Fixnum or Bignum (as required) int integer int
sfixed64 總是八個(gè)字節(jié)绢记。 int64 long int/long[4] int64 Bignum long integer/string[6] Int64
bool bool boolean bool bool TrueClass/FalseClass bool boolean bool
string 字符串必須始終包含 UTF-8 編碼或 7 位 ASCII 文本,并且長度不能超過 232正卧。 string String str/unicode[5] string String (UTF-8) string string String
bytes 可以包含不超過 232 的任意字節(jié)序列蠢熄。 string ByteString str (Python 2) bytes (Python 3) []byte String (ASCII-8BIT) ByteString string
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市炉旷,隨后出現(xiàn)的幾起案子签孔,更是在濱河造成了極大的恐慌,老刑警劉巖窘行,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饥追,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡罐盔,警方通過查閱死者的電腦和手機(jī)但绕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翘骂,“玉大人壁熄,你說我怎么就攤上這事帚豪√季梗” “怎么了草丧?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長莹桅。 經(jīng)常有香客問我昌执,道長,這世上最難降的妖魔是什么诈泼? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任懂拾,我火速辦了婚禮,結(jié)果婚禮上铐达,老公的妹妹穿的比我還像新娘岖赋。我一直安慰自己,他們只是感情好瓮孙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布唐断。 她就那樣靜靜地躺著,像睡著了一般杭抠。 火紅的嫁衣襯著肌膚如雪脸甘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天偏灿,我揣著相機(jī)與錄音丹诀,去河邊找鬼。 笑死翁垂,一個(gè)胖子當(dāng)著我的面吹牛铆遭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沿猜,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼枚荣,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了邢疙?” 一聲冷哼從身側(cè)響起棍弄,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疟游,沒想到半個(gè)月后呼畸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颁虐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年蛮原,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片另绩。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡儒陨,死狀恐怖花嘶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蹦漠,我是刑警寧澤椭员,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站笛园,受9級(jí)特大地震影響隘击,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜研铆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一埋同、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧棵红,春花似錦凶赁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至忆绰,卻和暖如春浩峡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背错敢。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國打工翰灾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稚茅。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓纸淮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親亚享。 傳聞我的和親對(duì)象是個(gè)殘疾皇子咽块,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 今天我們來一起聊一下序列化和反序列化,其實(shí)這兩個(gè)“活寶”對(duì)大家來說都不陌生欺税,而且也會(huì)覺得這有什么好聊的侈沪,其實(shí)筆者之...
    初夏的雪閱讀 862評(píng)論 0 1
  • 序列化 將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進(jìn)制串的過程。 反序列化 將在序列化過程中所生成的二進(jìn)制串轉(zhuǎn)換成數(shù)據(jù)結(jié)構(gòu)或者對(duì)象的...
    壹元伍角叁分閱讀 328評(píng)論 1 1
  • 序列化 定義以及相關(guān)概念 由于在系統(tǒng)底層晚凿,數(shù)據(jù)的傳輸形式是簡(jiǎn)單的字節(jié)序列形式傳遞亭罪,即在底層,系統(tǒng)不認(rèn)識(shí)對(duì)象歼秽,只認(rèn)識(shí)...
    WaterYuan閱讀 202評(píng)論 0 0
  • 序列化定義以及相關(guān)概念 定義:將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進(jìn)制串的過程应役。 由于在系統(tǒng)底層,數(shù)據(jù)的傳輸形式是簡(jiǎn)單的字節(jié)序...
    積跬步以致千里_ylc閱讀 689評(píng)論 0 0
  • 今天青石的票圈出鏡率最高的,莫過于張藝謀的新片終于定檔了盲泛。 一張滿溢著水墨風(fēng)的海報(bào)一次次的出現(xiàn)在票圈里濒持,也就是老謀...
    青石電影閱讀 10,350評(píng)論 1 2