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错误。接口

相关文章
相关标签/搜索