Serializeable

Java序列化

Java提供了一種對(duì)象序列化的機(jī)制,該機(jī)制中,一個(gè)對(duì)象可以被表示為一個(gè)字節(jié)序列化,該字節(jié)序列化包括該對(duì)象的數(shù)據(jù),有關(guān)對(duì)象的類(lèi)型的信息和存儲(chǔ)在對(duì)象中的數(shù)據(jù)類(lèi)型。
將序列化對(duì)象寫(xiě)入文件后,可以從文件中讀取出來(lái),并且對(duì)它進(jìn)行反序列化,也就是說(shuō),對(duì)象的類(lèi)型信息、對(duì)象的數(shù)據(jù),還有對(duì)象中的數(shù)據(jù)類(lèi)型可用用來(lái)在內(nèi)存中新建對(duì)象。
整個(gè)過(guò)程都是java虛擬機(jī)(JVM)獨(dú)立的,也就是說(shuō),在一個(gè)平臺(tái)上序列化的對(duì)象可以在另一個(gè)完全不同的平臺(tái)上反序列化該對(duì)象。

一個(gè)類(lèi)的對(duì)象想要序列化成功需要滿足:

1、該類(lèi)必須實(shí)現(xiàn)java.io.Serializable接口。
2、該類(lèi)中所有屬性必須是可序列化的,如果有一個(gè)屬性不可序列化,則該屬性必須注明是短暫的(transient)

注意

當(dāng)序列化一個(gè)對(duì)象到文件時(shí),按照J(rèn)ava的標(biāo)準(zhǔn)約定是給文件一個(gè).ser擴(kuò)展名(只是約定)

對(duì)于jvm可以反序列化對(duì)象,它必須是能夠找到字節(jié)碼的類(lèi),如果jvm在反序列化對(duì)象的過(guò)程中找不到該類(lèi),則拋出一個(gè)ClassNotFoundException異常。

@Data
@ToString
public class SerializeEntiy implements Serializable {

    private String name;

    private String address;

    private transient int SSN;

    private int number;

}

public class SerializeDemo {
    public static void main(String[] args) {
        //序列化
        serialize();
        //反序列化
        deserialization();
    }

    //反序列化
    private static void deserialization() {
        SerializeEntiy serialize = null;
        try {
            FileInputStream fileInput = new FileInputStream("/Users/Desktop/serilaize/serialize.ser");
            ObjectInputStream input = new ObjectInputStream(fileInput);
            serialize = (SerializeEntiy) input.readObject();
            input.close();
            fileInput.close();
            System.out.println(serialize);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //序列化
    private static void serialize() {
        SerializeEntiy serialize = new SerializeEntiy();
        serialize.setName("序列化");
        serialize.setAddress("北京市朝陽(yáng)區(qū)酒仙橋中路24號(hào)院");
        serialize.setNumber(878);
        serialize.setSSN(11);
        try {
            FileOutputStream fileOut = new FileOutputStream("/Users/Desktop/serilaize/serialize.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(serialize);
            out.close();
            fileOut.close();
            System.out.println("Serialized data is saved in /Users/qiangzhang/Desktop/serilaize/serialize.ser");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字段無(wú)法序列化的幾種場(chǎng)景:

1、靜態(tài)變量不會(huì)序列化
2、transient關(guān)鍵字指定的屬性
3、子類(lèi)實(shí)現(xiàn)Serializable接口而父類(lèi)沒(méi)有實(shí)現(xiàn)時(shí),父類(lèi)中的屬性是不會(huì)序列化的(父類(lèi)實(shí)現(xiàn)了子類(lèi)可以不用實(shí)現(xiàn))
4、當(dāng)序列化的類(lèi)的serializversionUID 發(fā)生改變時(shí),反序列化會(huì)失敗

主流的序列化技術(shù)有哪些:

JSON/Hessian(2)/xml/protobuf/kryo/MsgPack/FST/thrift/protosbuff/Avro

FST/kryo不支持跨語(yǔ)言

實(shí)現(xiàn)工具:(因環(huán)境不同,測(cè)試結(jié)果也有不同)

性能分析圖.png

JSON

        <!--   google     -->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.2</version>
        </dependency>
        <!--   alibaba     -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.74</version>
        </dependency>

性能分析:(可能會(huì)有差)Google的Jackson的序列化性能比Alibaba的fastjson性能要好,Alibaba的fastjson的反序列化性能比Google的Jackson性能要好,各有長(zhǎng)短

    public static void main(String[] args) throws IOException {

        excuteWithJackson();
        excuteWithFastJson();
    }

    //谷歌
    protected static void excuteWithJackson() throws IOException {
        User user = new User();
        user.setName("zhang");
        user.setAge(18);
        byte[] bytes = null;
        ObjectMapper objectMapper = new ObjectMapper();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            bytes = objectMapper.writeValueAsBytes(user);

        }
        System.out.println("Jackson序列化,time:" + (System.currentTimeMillis() - start) + "ms,總大小->" + bytes.length);
        long start1 = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            User user1 = objectMapper.readValue(bytes, User.class);
        }
        System.out.println("Jackson反序列化,time:" + (System.currentTimeMillis() - start1) + "ms,總大小->" + bytes.length);

//        System.out.println(user1);
    }

    //alibaba
    protected static void excuteWithFastJson() {
        User user = new User();
        user.setName("zhang");
        user.setAge(18);
        String json = null;
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            json = JSON.toJSONString(user);
        }
        System.out.println("FastJson序列化,time:" + (System.currentTimeMillis() - start) + "ms,總大小->" + json.getBytes().length);
        long start1 = System.currentTimeMillis();

        for (int i = 0; i < 10000; i++) {
            User user1 = JSON.parseObject(json, User.class);
        }
        System.out.println("FastJson反序列化,time:" + (System.currentTimeMillis() - start1) + "ms,總大小->" + json.getBytes().length);
    }

結(jié)果:

Jackson序列化,time:60ms,總大小->25
Jackson反序列化,time:65ms,總大小->25
FastJson序列化,time:80ms,總大小->25
FastJson反序列化,time:40ms,總大小->25

protobuff(Google)

性能:壓縮率高(字節(jié)數(shù)?。?,耗時(shí)短

        <dependency>
            <groupId>com.baidu</groupId>
            <artifactId>jprotobuf</artifactId>
            <version>2.4.4</version>
        </dependency>
  protected static void excuteWithProtoBuff() throws IOException {
        User user = new User();
        user.setName("zhang");
        user.setAge(18);
        byte[] encode = null;
        Codec<User> userCodec = ProtobufProxy.create(User.class, false);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            encode = userCodec.encode(user);
        }
        System.out.println("ProtoBuff序列化,time:" + (System.currentTimeMillis() - start) + "ms,總大小->" + encode.length);
        long start1 = System.currentTimeMillis();

        for (int i = 0; i < 10000; i++) {
            User user1 = userCodec.decode(encode);
        }
        System.out.println("ProtoBuff反序列化,time:" + (System.currentTimeMillis() - start1) + "ms");
    }
ProtoBuff序列化,time:29ms,總大小->9
ProtoBuff反序列化,time:2ms

Hessian

性能:壓縮率比較低(字節(jié)數(shù)大),時(shí)間短

        <dependency>
            <groupId>com.caucho</groupId>
            <artifactId>hessian</artifactId>
            <version>4.0.63</version>
        </dependency>
    protected static void excuteWithHessian() throws IOException {
        User user = new User();
        user.setName("zhang");
        user.setAge(18);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        HessianOutput hessianOutput = new HessianOutput(os);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            hessianOutput.writeObject(user);
            if(i == 1){
                System.out.println("總大小->" +os.toByteArray().length);
            }

        }
        System.out.println("Hessian序列化,time:" + (System.currentTimeMillis() - start) + "ms,");

        HessianInput hessianInput = new HessianInput(new ByteArrayInputStream(os.toByteArray()));

        long start1 = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            User user1 = (User)hessianInput.readObject();
        }
        System.out.println("Hessian反序列化,time:" + (System.currentTimeMillis() - start1) + "ms");
    }
總大小->61
Hessian序列化,time:2ms,
Hessian反序列化,time:5ms
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容