從源碼解析JAVA序列化是否需要空參構(gòu)造方法秩铆?

發(fā)現(xiàn)網(wǎng)絡(luò)上對(duì)于反序列化時(shí),什么時(shí)候需要空參構(gòu)造器都模糊不清噪叙,也沒(méi)有一個(gè)準(zhǔn)確的一個(gè)概念矮锈,因此我們由現(xiàn)象到源碼一探究竟

  1. 先上一個(gè)父類(lèi)和子類(lèi)都沒(méi)有空參構(gòu)造器,父類(lèi)實(shí)現(xiàn)Serializable接口睁蕾,子類(lèi)間接實(shí)現(xiàn)Serializable接口,序列化子類(lèi)對(duì)象sub
class Data implements Serializable{
    private int n;
    public Data(int n){
        this.n = n;
    }
    public String toString(){
        return Integer.toString(n);
    }
}

class sub extends Data{
    private static int m = 6;
    private int k;
    public sub(int n) {
        super(n);
    }
}
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("worm.out"));
        sub d = new sub(10);
        out.writeObject(d);

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("worm.out"));
        sub f = (sub) in.readObject();

序列化成功了苞笨,說(shuō)明這種情況父類(lèi)子類(lèi)不需要空參構(gòu)造器,序列化出來(lái)的文件是這樣的

?í ?sr main.subbê??uéaP? ?I ?kxr   main.Data?????t÷?? ?I ?nxp   
  1. 接下來(lái)嘗試父類(lèi)和子類(lèi)都沒(méi)有空參構(gòu)造器子眶,父類(lèi)不實(shí)現(xiàn)Serializable接口瀑凝,子類(lèi)實(shí)現(xiàn)Serializable接口,序列化子類(lèi)對(duì)象sub
class Data{
    private int n;
    public Data(int n){
        this.n = n;
    }
    public String toString(){
        return Integer.toString(n);
    }
}

class sub extends Data implements Serializable{
    private static int m = 6;
    private int k;
    public sub(int n) {
        super(n);
    }
}
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("worm.out"));
        sub d = new sub(10);
        out.writeObject(d);

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("worm.out"));
        sub f = (sub) in.readObject();

結(jié)果會(huì)發(fā)現(xiàn)提示找不到可用的構(gòu)造器

Exception in thread "main" java.io.InvalidClassException: main.sub; no valid constructor
    at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:150)
    at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:790)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1782)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
    at main.Worm.main(Worm.java:81)

序列化出的文件是這樣的

?í ?sr main.subμ|?)CO?I? ?I ?kxp    

會(huì)什么會(huì)出現(xiàn)這種情況呢,最后我們追蹤到ObjectStreamClass類(lèi)的一個(gè)方法,是引起異常的主要原因

//ObjectStreamClass.java
    /**
     * Returns subclass-accessible no-arg constructor of first non-serializable
     * superclass, or null if none found.  Access checks are disabled on the
     * returned constructor (if any).
     */
    private static Constructor<?> getSerializableConstructor(Class<?> cl) {
        Class<?> initCl = cl;
        while (Serializable.class.isAssignableFrom(initCl)) {
            if ((initCl = initCl.getSuperclass()) == null) {
                return null;
            }
        }
        try {
            Constructor<?> cons = initCl.getDeclaredConstructor((Class<?>[]) null);
            int mods = cons.getModifiers();
            if ((mods & Modifier.PRIVATE) != 0 ||
                ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
                 !packageEquals(cl, initCl)))
            {
                return null;
            }
            cons = reflFactory.newConstructorForSerialization(cl, cons);
            cons.setAccessible(true);
            return cons;
        } catch (NoSuchMethodException ex) {
            return null;
        }
    }

方法的注釋是

Returns subclass-accessible no-arg constructor of first non-serializable superclass, or null if none found. Access checks are disabled on the returned constructor (if any)臭杰。

翻譯過(guò)來(lái)的意思就是粤咪,返回第一個(gè)非可序列化超類(lèi)的子類(lèi)可訪問(wèn)的no-arg構(gòu)造函數(shù),如果沒(méi)有找到則返回null渴杆。在返回的構(gòu)造函數(shù)上禁用訪問(wèn)檢查(如果有的話)寥枝。

因此我們就明白了
為什么在第一個(gè)例子中沒(méi)有丟出InvalidClassException異常,因?yàn)榈谝粋€(gè)例子的第一個(gè)非可序列化超類(lèi)是Object磁奖,Object沒(méi)有顯式的構(gòu)造方法囊拜,因此就是默認(rèn)有默認(rèn)的空參構(gòu)造方法,符合條件

第二個(gè)例子中丟出InvalidClassException異常是因?yàn)榈诙€(gè)例子的第一個(gè)非可序列化超類(lèi)是Date,因?yàn)镈ate沒(méi)有顯示的構(gòu)造方法比搭,因此丟出異常

最后我們驗(yàn)證一下冠跷,如果給Date類(lèi)加上默認(rèn)空參構(gòu)造方法,是否還能編譯通過(guò)

class Data{
    private int n;
    public Data(int n){
        this.n = n;
    }
    public Data(){
        this.n = 10;
    }
    public String toString(){
        return Integer.toString(n);
    }
}

最后返回成功了,這也驗(yàn)證了我們的想法蜜托。

最后我們得到的結(jié)論是抄囚,序列化時(shí),如果第一個(gè)非可序列化超類(lèi)非Object類(lèi)橄务,那么一定要預(yù)留一個(gè)空參構(gòu)造方法幔托,否則就會(huì)序列化失敗

關(guān)于其他JAVA序列化的結(jié)論驗(yàn)證可以查看我的另一篇文章
http://www.reibang.com/p/7340dcb80a54

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蜂挪,隨后出現(xiàn)的幾起案子柑司,更是在濱河造成了極大的恐慌,老刑警劉巖锅劝,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攒驰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡故爵,警方通過(guò)查閱死者的電腦和手機(jī)玻粪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)诬垂,“玉大人劲室,你說(shuō)我怎么就攤上這事〗峋剑” “怎么了很洋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)隧枫。 經(jīng)常有香客問(wèn)我喉磁,道長(zhǎng),這世上最難降的妖魔是什么官脓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任协怒,我火速辦了婚禮,結(jié)果婚禮上卑笨,老公的妹妹穿的比我還像新娘孕暇。我一直安慰自己,他們只是感情好赤兴,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布妖滔。 她就那樣靜靜地躺著,像睡著了一般桶良。 火紅的嫁衣襯著肌膚如雪座舍。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,874評(píng)論 1 314
  • 那天艺普,我揣著相機(jī)與錄音簸州,去河邊找鬼。 笑死歧譬,一個(gè)胖子當(dāng)著我的面吹牛岸浑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瑰步,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼矢洲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了缩焦?” 一聲冷哼從身側(cè)響起读虏,我...
    開(kāi)封第一講書(shū)人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎袁滥,沒(méi)想到半個(gè)月后盖桥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡题翻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年揩徊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嵌赠。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡塑荒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出姜挺,到底是詐尸還是另有隱情齿税,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布炊豪,位于F島的核電站凌箕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏词渤。R本人自食惡果不足惜陌知,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掖肋。 院中可真熱鬧仆葡,春花似錦、人聲如沸志笼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纫溃。三九已至腰涧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間紊浩,已是汗流浹背窖铡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工疗锐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人费彼。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓滑臊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親箍铲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子雇卷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • JAVA序列化機(jī)制的深入研究 對(duì)象序列化的最主要的用處就是在傳遞,和保存對(duì)象(object)的時(shí)候,保證對(duì)象的完整...
    時(shí)待吾閱讀 10,878評(píng)論 0 24
  • 官方文檔理解 要使類(lèi)的成員變量可以序列化和反序列化,必須實(shí)現(xiàn)Serializable接口颠猴。任何可序列化類(lèi)的子類(lèi)都是...
    獅_子歌歌閱讀 2,414評(píng)論 1 3
  • 先貼上來(lái)源 https://rhettinger.wordpress.com/2011/05/26/super-c...
    奇豆寶閱讀 588評(píng)論 0 50
  • 這學(xué)期的目標(biāo)為沖刺一等獎(jiǎng)學(xué)金準(zhǔn)備 參加創(chuàng)新大賽 準(zhǔn)備英語(yǔ)中級(jí)口譯 準(zhǔn)備考研英語(yǔ)关划,高數(shù)
    五月sn閱讀 94評(píng)論 0 0
  • 轉(zhuǎn)載自http://blog.csdn.net/yhao2014/article/details/51554910...
    xbinng閱讀 542評(píng)論 0 1