• Java序列化机制


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

  • 相关阅读:
    vue-cli3 中跨域解决方案
    自定义超链接动画---transition
    Vue 单选框与单选框组 组件
    js 控制随机数生成概率
    Vue slot插槽
    vue 组件通信
    vue中computed计算属性与methods对象中的this指针
    C#提取html中的汉字
    MVC几种找不到资源的解决方式
    使用Windows服务定时去执行一个方法的三种方式
  • 原文地址:https://www.cnblogs.com/java-wgm/p/7217951.html
Copyright © 2020-2023  润新知