Java序列化的幾種特殊情景

package com.sdmjhca.springBootDemo.serializable;

import java.io.*;

/**
 * @author JHMI on 2017/8/29. jdk1.8
 * 情景1:靜態變量序列化
 * static 修飾的變量是類的變量
 * 序列化保存的是對象的狀態,所以序列化不會保存靜態變量
 *
 * 情景2transient關鍵字的作用是控制變量不被序列化,在反序列化後,transient變量的值被設爲初始值,String 默認爲null int默認爲0
 * 父類不實現serializable 父類中的變量也會被序列化(包括transient修飾的變量)
 * 父類實現serializable 父類中的transient變量不被序列化,非transient變量會被子類序列化
 *
 * 情景3:敏感數據加密
 * 定義私有的private void writeObjectprivate void readObject方法
 * Java序列化的時候,對敏感數據password進行加解密操作
 * 客戶端將加密後的password序列化後傳輸給服務端
 * 服務端在反序列化後,使用公鑰對password進行解密操作
 *
 * 情景4:序列化的存儲規則
 * 序列化同一個對象時,第二次文件大小隻增加5個字節,並且反序列化的兩個對象==判斷相同,是同一個對象。
 * 存儲規則:當序列化第二個對象如果和第一個對象相同,則第二次只會存儲該對象的引用,極大的節省了存儲空間
 *
 * 情景5:單例模式如果可序列化
 * 使用單例模式時,通常希望這個對象是唯一的,但是如果該類是可序列化的,
 * 單例模式初始化的對象 和 反序列化生成的對象不一致,可以通過重寫readResolve方法保證單例模式的特性
 */
public class SerializableTest  implements Serializable{

    public static int X = 100;
    public String s = "序列化";
    static ObjectOutputStream out;
    static ObjectInputStream in;
    /*public static void main(String[] args) {
        String path = "C:/read.out";
        try {
            new SerializableTest().modify();
            out = new ObjectOutputStream(new FileOutputStream(path));
            out.writeObject(new SerializableTest());
            //序列化完成後修改靜態變量的值
            //執行反序列化
            in = new ObjectInputStream(new FileInputStream(path));
            SerializableTest test = (SerializableTest) in.readObject();
            test.output(test);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(out != null ){
                    out.close();
                }
                if(in !=null){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }*/

    public  void modify(){
        X = 200;
        s = "反序列化";
    }

    public void output(SerializableTest test){
        System.out.println(test.X);
        System.out.println(test.s);
    }
    //-----------------------------情景2---------------------
    /*public static void main(String[] args) {
        String path = "C:/read.out";
        try {
            new SerializableTest().modify();
            out = new ObjectOutputStream(new FileOutputStream(path));
            out.writeObject(new SerializableTestSon());

            in = new ObjectInputStream(new FileInputStream(path));
            SerializableTestSon test = (SerializableTestSon) in.readObject();
            System.out.println("父類整形變量:"+test.anInt);
            System.out.println("父類字符串類型變量:"+test.attr);
            System.out.println("sonlei="+test.attrSon);
            System.out.println("tranzent="+test.intSon);
            System.out.println("not transint="+test.i);
            System.out.println("not transint="+test.ar);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(out != null ){
                    out.close();
                }
                if(in !=null){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }*/
    //------------------------情景3------------------------
    /*private String password;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    private void writeObject(ObjectOutputStream out){
        try {
            ObjectOutputStream.PutField putField = out.putFields();
            password = "entry";
            System.out.println("加密後的密碼="+password);
            putField.put("password",password);

            //向流中添加參數
            out.writeFields();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readObject(ObjectInputStream in){
        try {
            ObjectInputStream.GetField getField = in.readFields();
            password = (String) getField.get("password",null);
            System.out.println("解密前="+password);
            //解密操作
            password= "pass";
            System.out.println("解密後="+password);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        String path = "C:/read.out";
        try {
            out = new ObjectOutputStream(new FileOutputStream(path));
            out.writeObject(new SerializableTest());

            in = new ObjectInputStream(new FileInputStream(path));
            SerializableTest test = (SerializableTest) in.readObject();
            System.out.println(test.getPassword());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(out != null ){
                    out.close();
                }
                if(in !=null){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }*/
//------------------------情景4----------------------------------
    /*public static void main(String[] args) {
        String path = "C:/read.out";
        try {
            File file = new File(path);
            SerializableTest outTest = new SerializableTest();
            out = new ObjectOutputStream(new FileOutputStream(file));
            out.writeObject(outTest);
            System.out.println(file.length());

            out.writeObject(new SerializableTest());
            System.out.println(file.length());

            out.writeObject(outTest);
            System.out.println(file.length());

            in = new ObjectInputStream(new FileInputStream(path));
            SerializableTest test = (SerializableTest) in.readObject();
            SerializableTest test2 = (SerializableTest) in.readObject();
            SerializableTest test3 = (SerializableTest) in.readObject();
            System.out.println(test.equals(outTest) );
            System.out.println(test.equals(test3));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(out != null ){
                    out.close();
                }
                if(in !=null){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }*/
    //-----------------------------情景5單例模式----------------------
    public static void main(String[] args) {
        String path = "C:/read.out";
        try {
            File file = new File(path);
            Singleton outTest = Singleton.getSingleton();
            out = new ObjectOutputStream(new FileOutputStream(file));
            out.writeObject(outTest);

            in = new ObjectInputStream(new FileInputStream(path));
            Singleton test = (Singleton) in.readObject();
            System.out.println(test.equals(outTest) );
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(out != null ){
                    out.close();
                }
                if(in !=null){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
class Singleton implements Serializable{
    private Singleton(){}
    private static final Singleton singleton = new Singleton();
    public static Singleton getSingleton(){
        return singleton;
    }

    /**
     * 進行反序列化時返回同一個對象
     * 無論是實現Serializable接口,或是Externalizable接口,當從I/O流中讀取對象時,
     * readResolve()方法都會被調用到。實際上就是用readResolve()中返回的對象直接替換在反序列化過程中創建的對象,
     * 而被創建的對象則會被垃圾回收掉。
     * @return
     */
    private Object readResolve(){
        return singleton;
    }
}

參考:https://www.ibm.com/developerworks/cn/java/j-lo-serial/index.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章