一次搞懂序列化和反序列化

  1. 爲何須要序列化?

由於若是不實現序列化,那麼則沒法反序列化java

  1. 序列化使用場景?
  1. 須要存儲對象,好比說我如今須要把內存中的對象暫時寫入硬盤,等我係統啓用時在加載到內存反序列化後繼續使用。
  2. 須要遠程傳輸對象,則須要實現序列化接口,大多在socket網絡套接字編程場景中比較常見, 有同窗可能說,我常常使用socket傳輸數據,確沒有實現序列化接口,由於不少狀況下咱們都是傳輸的String字符串,而在Java中String已經實現了Serializable接口
  1. 序列化常見出錯問題?編程

    不實現序列化接口進行保存對象會出現以下錯誤,能夠經過實現Serializable接口解決問題。網絡

Exception in thread "main" java.io.NotSerializableException: home.s.Rule
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at home.s.Serial.main(Serial.java:13)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
修改序列號id則會出現以下問題:
Exception in thread "main" java.io.InvalidClassException: home.s.Rule; local class incompatible: stream classdesc serialVersionUID = 1234000, local class serialVersionUID = 123400
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
    at home.s.DESerial.main(DESerial.java:13)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
出現這個問題是由於序列號被認爲改動致使。這時可能大多數同窗會說,可不能夠不使用序列號,而使用Java自己默認的。

以下是Java默認生成序列號源碼,大概意思請自行閱讀。
/**
     * Return the serialVersionUID for this class.  The serialVersionUID
     * defines a set of classes all with the same name that have evolved from a
     * common root class and agree to be serialized and deserialized using a
     * common format.  NonSerializable classes have a serialVersionUID of 0L.
     *
     * @return  the SUID of the class described by this descriptor
     */
    public long getSerialVersionUID() {
        // REMIND: synchronize instead of relying on volatile?
        if (suid == null) {
            suid = AccessController.doPrivileged(
                new PrivilegedAction<Long>() {
                    public Long run() {
                        return computeDefaultSUID(cl);
                    }
                }
            );
        }
        return suid.longValue();
    }
可是這裏仍是強烈建議使用一個序列化版本號,由於默認的版本號很是敏感,而且依賴於編譯器,若是實體類在序列化以前和以後數據結構有所改變,則會致使以下問題:
Exception in thread "main" java.io.InvalidClassException: home.s.Rule; local class incompatible: stream classdesc serialVersionUID = -1031401772392262459, local class serialVersionUID = 7635324993874063726
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
    at home.s.DESerial.main(DESerial.java:13)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
  1. 具體測試源碼以下:數據結構

    實體類:app

package home.s;

import java.io.Serializable;

public class Rule  implements Serializable{
    private static final long serialVersionUID = 1234000L;
    public Rule(Long id, String type) {
        this.id = id;
        this.type = type;
    }

    private Long id;
    private String type;
   // private String name;


    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }


 /*   public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }*/
}
序列化
Rule rule = new Rule(1232L, "asdf");
        FileOutputStream fileOutputStream = new FileOutputStream(new File("d:\\222.txt"));
        ObjectOutputStream oos = new ObjectOutputStream(fileOutputStream);
        oos.writeObject(rule);
        oos.flush();
        fileOutputStream.close();
反序列化
FileInputStream fis = new FileInputStream(new File("D:\\222.txt"));
        ObjectInputStream ois = new ObjectInputStream(fis);
        Rule o = (Rule) ois.readObject();
        System.out.println(Json.toJson(o));
相關文章
相關標籤/搜索