1. 程式人生 > >Jackson反序列化問題

Jackson反序列化問題

JackSon和內部類,是的,你可以使用,但他們必須是靜態的內部類。


這是我直到今天沒有意識到的東西:這顯然是正確使用內部類在Java開發者社群的巨大的困惑。事實上有一些網頁顯示

JackSon不能使用內部類值。

這實際上是真實的和虛假的,原因就在於Java的內部類的特點。早在Java 1.1的時候就引入了內部類(為了使AWT以及後

來的Swing更容易使用),但不是每個人都懂得如何適當地使用內部類。

1.長話短說

你可以這樣使用靜態內部類:
public class Outer {
    static class Inner {
        public int getX() { return 5;
    }
}    
值沒有任何問題。只要確保“靜”在那裡。

如果你的內部類不是靜態的,那麼所得到的類通常是JackSon以及任何其他資料繫結框架無用(Hibernate,JAXB)不可以

使用的;通常可以被序列化,但不可以反序列化。要理解為什麼,需要我們回到過去,90年代末…第一批語法糖加入Java



2.匿名的,靜態的,非靜態內部類

一共有三種內部類形式: 匿名內部類是在一條語句中使用的 (如事件處理函式); 靜態內部類是用static修飾符修飾的類

; 普通內部類類似靜態內部類,區別在於沒有static修飾.

這裡最重要的區別在於有麼有static修飾. 修飾符選擇不是很直觀的, 它真正的意思是:非靜態內部類(包括匿名內部類

)被編譯器通過隱藏的構造器傳遞了一組隱藏變數.直接結果就是, 無預設建構函式 -- 即使程式碼裡面確實有一個無參的

建構函式可以使用。

所以,如果你的程式碼是這樣寫的:

  public class Outer {
   class Inner { // non-static
     public int getX() { return 3; }
   }
  }

實際上編譯器會這樣生成:

public class Outer { ... }

class Outer$Inner {
  private final Outer parent;

  Outer$Inner(Outer p) {
    parent = p;
  }
  public int getX() { return 3; }
}

(同樣的,內部類可以訪問外部類的所有程式碼)

為什麼會這樣? 因為這樣內部類內部就可以訪問外部類的所有程式碼,包括私有程式碼;在匿名的情況下(內建)內部類,

甚至看似範圍內的變數(這只是霧裡看花 - 最後變數作為傳遞只是更隱蔽建構函式的引數)。

靜態內部類只是普通的類,無任何隱藏內容。實際上它跟二級類(含有公開類的檔案中宣告的非公開類,使用封閉的命名

空間)除名字以外並無本質區別。

3。所以關於JackSon,內部類…?

JackSon拒絕嘗試使用非靜態內部類的基本原因(序列化是可以正常工作的)是因為這樣的類沒有例項化的一般方法,沒

有零引數的建構函式,也沒有@jsoncreator註釋其他建構函式或工廠方法(或單個字串引數的建構函式),所以

JackSon不能例項化它們。

在理論上可以如果得知所包圍的父類例項是什麼,那麼就可以處理這種情況。但實際上這是複雜的和不必要的——典型的

static缺失是意外或者疏忽,通過增加給內部類增加static就可以讓程式碼很好的工作。