@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ì)象。