Jackson反序列化問題
阿新 • • 發佈:2018-12-26
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就可以讓程式碼很好的工作。