Serializable对象完全以它存储的二进制位为基础来反序列化,而不必调用构造器。对于一个Externalizable对象,所有的默认构造器都会被调用(包括在字段定义时的初始化),然后调用readExternal()方法来反序列化。因此,为了正常运行, 我们需要在writeExternal()将来自对象的重要信息写入(你要序列化的信息), 然后用readExternal()读取你之前序列化的对象信息。以两段代码为例:

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

1)进行对象的实例化;

2)将对象序列化到本地,保存在se.pkl文件中, 此处在writeObject()后会调用writeExternal(ObjectOutput out)方法完成对象信息的序列化,即控制序列化对象的那些信息;

3)从本地反序列化对象,并打印输出。在此过程中会在readObject()后先调用默认构造器,以及第10行字段初始化,然后调用readExternal(ObjectInput in)完成对象信息的反序列化。

在实际的应用过程中, 对于一些敏感信息,我们并不希望被序列化,上述代码中虽然name, age都是private私有字段, 但通过序列化机制,外部依然可以获取到他们的值, 为了隐蔽掉对象的敏感信息, 我们可以使用transient关键字修饰敏感字段,这样在序列化对象时,将剔除对该字段的序列化。也可以在Externalizable对象中,通过writeExternal()进行显示序列化。如下:

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

posted on 2017-07-21 15:37  pattywgm  阅读(479)  评论(0编辑  收藏  举报