Java8的lambda(2)

来源:互联网 发布:极装吉住靠谱吗 知乎 编辑:程序博客网 时间:2024/05/16 14:03

在开始之前,我先普及一下什么是Single Abstract Method interfaces (SAM Interfaces).简单的说就是只用一个函数的interface。

例如Runnable,Comparable等;

例如下面一个:

package functional;@FunctionalInterfacepublic interface SimpleFuncInterface {  public void doWork();    public String toString();}


lambda就是通过MethodHandle来实现的。

那么在运行的过程中,它是什么样子的呢?

看看下面的例子:

package functional;public class SimpleFunInterfaceTest2 {public static void main(String[] args) {// lambdacarryOutWork(() -> 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);


0 0
原创粉丝点击