Java序列化機制

Serializable對象徹底以它存儲的二進制位爲基礎來反序列化,而沒必要調用構造器。對於一個Externalizable對象,全部的默認構造器都會被調用(包括在字段定義時的初始化),而後調用readExternal()方法來反序列化。所以,爲了正常運行, 咱們須要在writeExternal()未來自對象的重要信息寫入(你要序列化的信息), 而後用readExternal()讀取你以前序列化的對象信息。以兩段代碼爲例:java

import java.io.*;

/**
 * Version: 3.0
 * Author: pattywgm
 * Time: 17/7/21 下午2:53
 * Desc:
 */
public class SerializationTest implements Serializable {
    private String name;
    private int age;

    public SerializationTest(){};

    public SerializationTest(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String toString(){
        return "Name is: "+ this.name + " and age is: " + this.age;
    }

    public static void main(String[] args){
        SerializationTest serializationTest = new SerializationTest("wkl", 27);    // 1)
        try {
            ObjectOutput output =  new ObjectOutputStream(new FileOutputStream("se.pkl"));   // 2)
            output.writeObject(serializationTest);

            ObjectInput input = new ObjectInputStream(new FileInputStream("se.pkl"));   
            System.out.println(input.readObject().toString());  // 3)
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

上述代碼實現了Serializable接口, 1)進行對象的實例化, 2)將對象序列化到本地,保存在se.pkl文件中  3)從本地反序列化對象,並打印輸出。在此過程當中不涉及對默認構造函數的調用。函數

 1 import java.io.*;
 2 
 3 /**
 4  * Version: 3.0
 5  * Author: pattywgm
 6  * Time: 17/7/21 下午3:02
 7  * Desc:
 8  */
 9 public class ExternizationalTest implements Externalizable {
10     private String name = new String("zzk");
11     private int age;
12 
13     public ExternizationalTest(){};
14 
15     public ExternizationalTest(String name, int age){
16         this.name = name;
17         this.age = age;
18     }
19 
20 
21 
22     public void writeExternal(ObjectOutput out) throws IOException {
23         System.out.println("Write object....");
24         out.writeObject(this.name);
25         out.writeInt(this.age);
26     }
27 
28     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
29         System.out.println("Read object....");
30         this.name = (String)in.readObject();
31         this.age = in.readInt();
32     }
33 
34     public String toString(){
35         return "Name is: "+ this.name + " and age is: " + this.age;
36     }
37 
38     public static void main(String[] args){
39         ExternizationalTest externizationalTest = new ExternizationalTest("wkl", 27);     // 1)
40         try {
41             ObjectOutput output =  new ObjectOutputStream(new FileOutputStream("se1.pkl"));  // 2)
42             output.writeObject(externizationalTest);
43 
44             ObjectInput input = new ObjectInputStream(new FileInputStream("se1.pkl"));  // 3)
45             System.out.println(input.readObject().toString());
46         } catch (IOException e) {
47             e.printStackTrace();
48         } catch (ClassNotFoundException e) {
49             e.printStackTrace();
50         }
51     }
52 }

上述代碼實現了Externalizable接口。this

1)進行對象的實例化;spa

2)將對象序列化到本地,保存在se.pkl文件中, 此處在writeObject()後會調用writeExternal(ObjectOutput out)方法完成對象信息的序列化,即控制序列化對象的那些信息;code

3)從本地反序列化對象,並打印輸出。在此過程當中會在readObject()後先調用默認構造器,以及第10行字段初始化,而後調用readExternal(ObjectInput in)完成對象信息的反序列化。對象

在實際的應用過程當中, 對於一些敏感信息,咱們並不但願被序列化,上述代碼中雖然name, age都是private私有字段, 但經過序列化機制,外部依然能夠獲取到他們的值, 爲了隱蔽掉對象的敏感信息, 咱們能夠使用transient關鍵字修飾敏感字段,這樣在序列化對象時,將剔除對該字段的序列化。也能夠在Externalizable對象中,經過writeExternal()進行顯示序列化。以下:blog

import java.io.*;

/**
 * Version: 3.0
 * Author: pattywgm
 * Time: 17/7/21 下午2:53
 * Desc:
 */
public class SerializationTest implements Serializable {
    private String name;
    private int age;
    private transient String password;    // 該字段不會被序列化

    public SerializationTest(){};

    public SerializationTest(String name, int age, String password){
        this.name = name;
        this.age = age;
        this.password = password;
    }

    public String toString(){
        return "Name is: "+ this.name +
                " and age is: " + this.age +
                " and password is: " + this.password;
    }

    public static void main(String[] args){
        SerializationTest serializationTest = new SerializationTest("wkl", 27, "123456");
        try {
            ObjectOutput output =  new ObjectOutputStream(new FileOutputStream("se.pkl"));
            output.writeObject(serializationTest);

            ObjectInput input = new ObjectInputStream(new FileInputStream("se.pkl"));
            System.out.println(input.readObject().toString());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
import java.io.*;

/**
 * Version: 3.0
 * Author: pattywgm
 * Time: 17/7/21 下午3:02
 * Desc:
 */
public class ExternizationalTest implements Externalizable {
    private String name = new String("zjm");
    private int age;
    private String password;    // 該字段不會被序列化

    public ExternizationalTest(){};

    public ExternizationalTest(String name, int age, String password){
        this.name = name;
        this.age = age;
        this.password = password;
    }



    public void writeExternal(ObjectOutput out) throws IOException {
        System.out.println("Write object....");
        out.writeObject(this.name);
        out.writeInt(this.age);
    }

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        System.out.println("Read object....");
        this.name = (String)in.readObject();
        this.age = in.readInt();
    }

    public String toString(){
        return "Name is: "+ this.name +
                " and age is: " + this.age +
                " and password is: " + this.password;    }

    public static void main(String[] args){
        ExternizationalTest externizationalTest = new ExternizationalTest("wkl", 27, "123456");
        try {
            ObjectOutput output =  new ObjectOutputStream(new FileOutputStream("se1.pkl"));
            output.writeObject(externizationalTest);

            ObjectInput input = new ObjectInputStream(new FileInputStream("se1.pkl"));
            System.out.println(input.readObject().toString());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

 若是此時咱們在SerializationTest類中引用外部一個UserInfo對象,須要注意,該UserInfo對象必須是可序列化的,即實現了Serializable接口, 不然會在運行時報java.io.NotSerializableException: com.patty.jedis.demo.UserInfo錯誤。接口

相關文章
相關標籤/搜索