在开始之前,我先普及一下什么是Single Abstract Method interfaces (SAM Interfaces).简单的说就是只用一个函数的interface。
例如Runnable,Comparable等;
例如下面一个:
package functional;
@FunctionalInterface
public interface SimpleFuncInterface {
public void doWork();
public String toString();
}
lambda就是通过MethodHandle来实现的。
那么在运行的过程中,它是什么样子的呢?
看看下面的例子:
package functional;
public class SimpleFunInterfaceTest2 {
public static void main(String[] args) {
// lambda
carryOutWork(() -> sleep());
carryOutWork(() -> sleep());
}
private static Object sleep() {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public static void carryOutWork(SimpleFuncInterface sfi) {
sfi.doWork();
}
}
在Thread.sleep那一行打个断点,这时的堆栈是:
"main" #1 prio=5 os_prio=0 tid=0x00e9cc00 nid=0x5e8 at breakpoint[0x001cf000]
java.lang.Thread.State: RUNNABLE
at functional.SimpleFunInterfaceTest.sleep(SimpleFunInterfaceTest.java:24)
at functional.SimpleFunInterfaceTest.lambda$0(SimpleFunInterfaceTest.java:20)
at functional.SimpleFunInterfaceTest$$Lambda$1/7599890.doWork(Unknown Source)
at functional.SimpleFunInterfaceTest.carryOutWork(SimpleFunInterfaceTest.java:34)
at functional.SimpleFunInterfaceTest.main(SimpleFunInterfaceTest.java:20)
JVM会生成一个7599890实例来实行对应的lambda,如果你再起一个同样的程序,这时的堆栈和第一次是一样的;
如果在第二次嗲用carryOutWork的Thread.sleep上停住的话,这是的堆栈就不一样了,如下图:
这是为什么呢?这是因为两次调用carryOutWork方法,都会在class文件中生成两个lambda方法,所以这里的实例对象不一样;
一个是25332239,一个是7599890.这里的数字应该是根据什么lambda的位置和实现的interface名字生成的,同一个lambda在不同的JVM实例中生成的数字是一样的,
这里应该就是CallSite了。
但是你如果想只生成一个lambda的话,应该怎么办呢?
SimpleFuncInterface sfi = () -> sleep();
carryOutWork(sfi);
carryOutWork(sfi);