关于for循环对lambda表达式的优化

故事的起源,是一段代码:

public static void main(String[] args) {


    I i = C::n; 
    I i2 = C::n;
    I i3 = C::n;
    System.out.println(i.getClass());
    System.out.println(i2.getClass());
    System.out.println(i3.getClass());
}

@FunctionalInterface
public interface I {
    void m();
}

public static class C {
    static void n() {
        System.out.println("hello");
    }
}

在JDK1.8之后,java终于也有了自己的一套用起来比较简洁方便的函数式编程的方式,其中lambda表达式就是其中比较关键的一步。
正常来说,java会预先编译好我们的java文件,将用到的class按需load到内存中。
不过随着时代的发展,各种第三方知名框架或类库,许多核心的实现更依赖于后续程序运行期间动态生成的一些class。

我们知道,在java中,真正可以干活的一定需要是某个类,而不是接口。在JDK8中诞生的lambda的运行背后也是如此,它也是会在声明了一个表达式之后,默默的动态生成了某个内部类。

你可以尝试分析一下,这段代码的最后打印的class会是几个呢?

运行结果:

class com.peng.run_time_data_area.T05_InvokeDynamic$$Lambda$1/1078694789
class com.peng.run_time_data_area.T05_InvokeDynamic$$Lambda$2/1023892928
class com.peng.run_time_data_area.T05_InvokeDynamic$$Lambda$3/558638686

是3个。 通过这段输出结果,我们知道了,每次lambda的声明,确实都会动态新产生一个Lambda的内部类。

这时候你回想一下你之前如果用过lambda表达式,有没有这种操作:就是在一个for循环里面进行声明了一个lambda表达式。 我觉得这种操作一般用lambda的人,都可能会有。

就是类似这种写法:

for (int j = 0; j < 5; j++) {
    I theLambda = C::n;
    System.out.println(theLambda.getClass());
}

按照我们刚才的理论,每次声明都会动态产生一个内部类,那我如果在一个for循环里声明,那岂不是会生成n个内部对象,而其实它们的作用是一样的,我是不是应该声明到外面去呢?

以前我也是这么想的,但一次偶然的机会,我发现和我想的不太一样。
看上面代码输出结果:

class com.peng.jvm.c4_RuntimeDataAreaAndInstructionSet.T05_InvokeDynamic$$Lambda$4/1149319664
class com.peng.jvm.c4_RuntimeDataAreaAndInstructionSet.T05_InvokeDynamic$$Lambda$4/1149319664
class com.peng.jvm.c4_RuntimeDataAreaAndInstructionSet.T05_InvokeDynamic$$Lambda$4/1149319664
class com.peng.jvm.c4_RuntimeDataAreaAndInstructionSet.T05_InvokeDynamic$$Lambda$4/1149319664
class com.peng.jvm.c4_RuntimeDataAreaAndInstructionSet.T05_InvokeDynamic$$Lambda$4/1149319664

呀? 奇怪,怎么都是一个对象呢。
这个lambda并没有像我想象的一样,产生了多个对象,而是这些循环都使用的是一个lambda的对象。
我猜测这大概是JDK for循环中对lambda做出的优化。
觉得很有意思,特此记录一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值