lambda函數(shù)序列化

@FunctionalInterface

public interface MyFunctionextends Function,Serializable{

}


public static void main(String[] args)throws IOException, ClassNotFoundException {

//第一種

? ? String dd =map((Function&Serializable) T::aa, "dd");

? ? System.out.println("result~~~~~~~"+dd);

? ? //第二種 在方法指定是序列化函數(shù)

? ? String yy =map1(T::aa, "dd");

? ? System.out.println("result~~~~~~~"+yy);

}

public static Stringaa(String pa){

System.out.println(pa);

? ? return pa +"~~~~~";

}

static??<U>?U map(Function<String, ?extends U> function,String a)throws IOException, ClassNotFoundException {

System.out.println(function);

? ? serialize(function, new FileOutputStream("lambda.obj"));

? ? Function func = (Function)deserialize(new FileInputStream("lambda.obj"));

? ? U apply = func.apply(a);

? ? System.out.println(apply);

? ? return apply;

}

static U map1(MyFunction function,String a)throws IOException, ClassNotFoundException {

System.out.println(function);

? ? serialize(function, new FileOutputStream("lambda.obj"));

? ? Function func = (Function)deserialize(new FileInputStream("lambda.obj"));

? ? U apply = func.apply(a);

? ? System.out.println(apply);

? ? return apply;

}

public static void serialize(Object obj, OutputStream out)throws IOException {

ObjectOutputStream objOut =new ObjectOutputStream(out);

? ? objOut.writeObject(obj);

? ? out.flush();

? ? out.close();

}

public static Objectdeserialize(InputStream in)throws IOException, ClassNotFoundException {

ObjectInputStream objIn =new ObjectInputStream(in);

? ? Object result = objIn.readObject();

? ? objIn.close();

? ? return result;

}

2. lambda序列化

如果我們使用這個(gè)命令運(yùn)行TestLambda:java -cp . -Djdk.internal.lambda.dumpProxyClasses=. TestLambda

程序運(yùn)行完成后器瘪,會(huì)在當(dāng)前目錄生成兩個(gè)class文件英支,TestLambda\$$Lambda$1.class和TestLambda\$$Lambda$4.class获黔。

writeReplace方法的作用是在該類實(shí)例序列化時(shí)哥桥,并不會(huì)真正序列化該類的對(duì)象期贫,而是將writeReplace方法返回的對(duì)象進(jìn)行序列化。所以,lambda對(duì)象序列化的時(shí)候,真正序列化的對(duì)象是SerializedLambda對(duì)象撮竿。

該SerializedLambda對(duì)象記錄如下信息:

? ? ? ? (1).lambda定義所在的Class對(duì)象? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? (2).lambda實(shí)現(xiàn)的函數(shù)式接口的全限定名

? ? ? ? (3).lambda實(shí)現(xiàn)的函數(shù)式接口的方法名

? ? ? ? (4).lambda實(shí)現(xiàn)的函數(shù)式接口的方法簽名

? ? ? ? (5).implMethodKind(這個(gè)含義我也沒弄明白)

? ? ? ? (6).lambda函數(shù)的真正實(shí)現(xiàn)方法所在的類名,和(1)中的Class對(duì)象相同笔呀,這里是類的全限定名

? ? ? ? (7).lambda函數(shù)的真正實(shí)現(xiàn)方法的方法名

? ? ? ? (8).lambda函數(shù)的真正實(shí)現(xiàn)方法的方法簽名

? ? ? ? (9).替換類型參數(shù)的函數(shù)式接口方法簽名

? ? ? ? (10).捕獲的參數(shù)

最終幢踏,這些信息,也就是上面代碼中new SerializedLambda對(duì)象傳進(jìn)去的參數(shù)许师,才是被序列化記錄的信息房蝉,這些信息都是在用于lambda的反序列化。

3.lambda反序列化

既然lambda序列化時(shí)記錄的是SerializedLambda對(duì)象微渠,那么我們來看SerializedLambda對(duì)象是怎么最終變成lambda對(duì)象的搭幻。

在SerializedLambda類的源碼中,我們可以看到有一個(gè)方法readResolve逞盆,這個(gè)方法的作用是在該類對(duì)象被反序列化時(shí)粗卜,將調(diào)用readResolve方法,該方法的返回對(duì)象才是反序列化返回的對(duì)象纳击。

從代碼中可以看出,反序列化SerializedLambda對(duì)象時(shí)攻臀,readResolve方法將會(huì)從capturingClass中尋找名為"$deserializeLambda$"的方法焕数。由上一節(jié)可知,capturingClass就是定義lambda對(duì)象所在的類對(duì)象刨啸,而$deserializeLambda$方法也是編譯器生成的隱藏方法堡赔,通過 javap -s -p -v -c -l TestLambda.class 查看字節(jié)碼,可以看到確實(shí)存在方法$deserializeLambda$设联。

由于這個(gè)方法字節(jié)碼比較長(zhǎng)善已,就不全部貼出來分析了灼捂,在這個(gè)方法中,會(huì)對(duì)上一節(jié)序列化記錄的信息進(jìn)行校驗(yàn)换团,校驗(yàn)正確悉稠,程序會(huì)調(diào)用invokeDynamic指令生成代表lambda的內(nèi)部類,并且創(chuàng)建該內(nèi)部類的對(duì)象艘包,然后返回作為反序列化的最終對(duì)象的猛。

簡(jiǎn)單來說,lambda對(duì)象的反序列化想虎,就是先反序列化出SerializedLambda對(duì)象卦尊,然后調(diào)用readResolve方法生成真正的lambda對(duì)象。

4.總結(jié)

(1).編譯器會(huì)在定義lambda函數(shù)的類中舌厨,生成靜態(tài)方法$deserializeLambda$(java.lang.invoke.SerializedLambda)岂却,該方法知曉由SerializedLambda對(duì)象生成lambda對(duì)象的具體細(xì)節(jié)。

(2).lambda對(duì)象運(yùn)行時(shí)生成的類裙椭,它有一個(gè)writeReplace方法躏哩,該方法將lambda的信息記錄在一個(gè)SerializedLambda對(duì)象中,然后將這個(gè)SerializedLambda對(duì)象序列化骇陈。它記錄了定義lambda所在的類震庭,lambda實(shí)現(xiàn)的函數(shù)式接口等。

(3).SerializedLambda對(duì)象定義的readResolve方法你雌,就是用于反序列化生成lambda對(duì)象的器联。

(4).lambda對(duì)象序列化整個(gè)流程:

lambda對(duì)象 --> writeReplace方法 --> SerializedLambda對(duì)象 --> 序列化的字節(jié) --> SerializedLambda對(duì)象 --> readResolve方法 --> $deserializeLambda$方法 --> lambda對(duì)象。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末婿崭,一起剝皮案震驚了整個(gè)濱河市拨拓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氓栈,老刑警劉巖渣磷,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異授瘦,居然都是意外死亡醋界,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門提完,熙熙樓的掌柜王于貴愁眉苦臉地迎上來形纺,“玉大人,你說我怎么就攤上這事徒欣≈鹧” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)脂新。 經(jīng)常有香客問我挪捕,道長(zhǎng),這世上最難降的妖魔是什么争便? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任级零,我火速辦了婚禮,結(jié)果婚禮上始花,老公的妹妹穿的比我還像新娘妄讯。我一直安慰自己,他們只是感情好酷宵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布亥贸。 她就那樣靜靜地躺著,像睡著了一般浇垦。 火紅的嫁衣襯著肌膚如雪炕置。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天男韧,我揣著相機(jī)與錄音朴摊,去河邊找鬼。 笑死此虑,一個(gè)胖子當(dāng)著我的面吹牛甚纲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播朦前,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼介杆,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了韭寸?” 一聲冷哼從身側(cè)響起春哨,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恩伺,沒想到半個(gè)月后赴背,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晶渠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年凰荚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褒脯。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浇揩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出憨颠,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布爽彤,位于F島的核電站养盗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏适篙。R本人自食惡果不足惜往核,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嚷节。 院中可真熱鬧聂儒,春花似錦、人聲如沸硫痰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽效斑。三九已至非春,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缓屠,已是汗流浹背奇昙。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留敌完,地道東北人储耐。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像滨溉,于是被迫代替她去往敵國和親什湘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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

  • 官方文檔理解 要使類的成員變量可以序列化和反序列化业踏,必須實(shí)現(xiàn)Serializable接口禽炬。任何可序列化類的子類都是...
    獅_子歌歌閱讀 2,409評(píng)論 1 3
  • 正如前文《Java序列化心得(一):序列化設(shè)計(jì)和默認(rèn)序列化格式的問題》中所提到的,默認(rèn)序列化方法存在各種各樣的問題...
    登高且賦閱讀 8,389評(píng)論 0 19
  • 在Java中勤家,我們可以通過多種方式來創(chuàng)建對(duì)象腹尖,并且只要對(duì)象沒有被回收我們都可以復(fù)用該對(duì)象。但是伐脖,我們創(chuàng)建出來的這些...
    懶癌正患者閱讀 1,530評(píng)論 0 12
  • 什么是序列化與反序列化 序列化是指把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程(Encoding an object as a by...
    小X感悟閱讀 884評(píng)論 0 4
  • 一.基本知識(shí) Java語言支持一種稱為對(duì)象序列化和反序列的機(jī)制热幔,它可以將任意對(duì)象寫出到流中,并在之后將其讀回讼庇,恢復(fù)...
    第四單元閱讀 601評(píng)論 0 4