先看一段代碼
public class Lambda {
public static void main(String[] args) {
System.setProperty("jdk.internal.lambda.dumpProxyClasses", ".");
Function<Integer, String> fun1 = String::valueOf;
Function<String, Integer> fun2 = String::length;
System.out.println(fun1.apply(1));
System.out.println(fun2.apply("hello"));
}
}
那麼,javac爲我們做了什麼呢?等價與那些代碼呢?
對於第一種爲
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup caller = MethodHandles.lookup();
String invokedName = "apply";
MethodType invokedType = MethodType.methodType(Function.class);
MethodHandle implMethod = caller.findStatic(String.class, "valueOf",
MethodType.methodType(String.class,int.class));
MethodType instantiatedMethodType = MethodType.methodType(String.class,int.class);
CallSite site = LambdaMetafactory.metafactory(caller,
invokedName,
invokedType,
instantiatedMethodType.generic(),
implMethod,
instantiatedMethodType);
MethodHandle factory = site.getTarget();
Function<Integer,String> fun1 = (Function<Integer,String>) factory.invoke();
System.out.println(fun1.apply(1));
}
第二種爲
MethodHandles.Lookup caller = MethodHandles.lookup();
String invokedName = "apply";
MethodType invokedType = MethodType.methodType(Function.class);
MethodHandle implMethod = caller.findVirtual(String.class, "length",
MethodType.methodType(int.class));
MethodType instantiatedMethodType = MethodType.methodType(int.class,String.class);
CallSite site = LambdaMetafactory.metafactory(caller,
invokedName,
invokedType,
instantiatedMethodType.generic(),
implMethod,
instantiatedMethodType);
MethodHandle factory = site.getTarget();
Function<String,Integer> fun2 = (Function<String,Integer>) factory.invoke();
System.out.println(fun2.apply("hello"));
生成的具體類爲
第一個
final class Lambda$$Lambda$1
implements Function {
private Lambda$$Lambda$1() {
}
@LambdaForm.Hidden
public Object apply(Object object) {
return String.valueOf((Integer)object);
}
}
第二個
final class Lambda$$Lambda$2
implements Function {
private Lambda$$Lambda$2() {
}
@LambdaForm.Hidden
public Object apply(Object object) {
return ((String)object).length();
}
}