当前位置: 首页 > news >正文

Lambda原理及应用

Lambda原理及应用

Lambda介绍

Lambda 是 JDK8 以后版本推出的一个新特性,也是一个重要的版本更新,利用 Lambda 可以简化内部类,可以更方便的进行集合的运算,让你的代码看起来更加简洁,也能提升代码的运行效率

Lambda语法

非静态类

(parameters...) -> expression

或者

(parameters...) ->{ statements; }

静态类

(parameters...) -> Class.Method(parameters...)

通常也可以简写成

Class::Method

举个例子

() -> 1 
i -> 2 * i  
(String s) -> {System.out.print(s);}
(o1, o2) -> Integer.compare(o1, o2)
Integer::compare

Lambda的原理

例子

我们来看下面的例子,使用 Lambda 实现一个 Runable 线程。

package org.lin;public class LambdaTest {public static void main(String[] args) {new Thread(() -> System.out.println("run")).start();}
}

分析一下它的字节码:

// access flags 0x21
public class org/lin/LambdaTest {// compiled from: LambdaTest.java// access flags 0x19public final static INNERCLASS java/lang/invoke/MethodHandles$Lookup java/lang/invoke/MethodHandles Lookup// access flags 0x1public <init>()VL0LINENUMBER 3 L0ALOAD 0INVOKESPECIAL java/lang/Object.<init> ()VRETURNL1LOCALVARIABLE this Lorg/lin/LambdaTest; L0 L1 0MAXSTACK = 1MAXLOCALS = 1// access flags 0x9public static main([Ljava/lang/String;)VL0LINENUMBER 6 L0NEW java/lang/ThreadDUPINVOKEDYNAMIC run()Ljava/lang/Runnable; [// handle kind 0x6 : INVOKESTATICjava/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;// arguments:()V, // handle kind 0x6 : INVOKESTATICorg/lin/LambdaTest.lambda$main$0()V, ()V]INVOKESPECIAL java/lang/Thread.<init> (Ljava/lang/Runnable;)VINVOKEVIRTUAL java/lang/Thread.start ()VL1LINENUMBER 7 L1RETURNL2LOCALVARIABLE args [Ljava/lang/String; L0 L2 0MAXSTACK = 3MAXLOCALS = 1// access flags 0x100Aprivate static synthetic lambda$main$0()VL0LINENUMBER 6 L0GETSTATIC java/lang/System.out : Ljava/io/PrintStream;LDC "run"INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)VRETURNMAXSTACK = 2MAXLOCALS = 0
}

关键指令

  INVOKEDYNAMIC run()Ljava/lang/Runnable; [// handle kind 0x6 : INVOKESTATICjava/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;// arguments:()V, // handle kind 0x6 : INVOKESTATICorg/lin/LambdaTest.lambda$main$0()V, ()V]

通过调用一个 INVOKEDYNAMIC 指令 ,将方法链接到这个方法上 org/lin/LambdaTest.lambda$main$0()V

这个方法的命名方式 ,很可能 JDK 内部帮我们生成了一个内部类, org/lin/LambdaTest.lambda$main

通过 jclasslib 工具查看,验证了我们的想法:
在这里插入图片描述

Invokedynamic 和 LambdaMetafactory

Invokedynamic

Invokedynamic 是 JDK7 引入的一条新指令,通过一个调用点 CallSite 和 方法句柄 MethodHandle,来完成一个方法的调用。
CallSite 就是一个 MethodHandle 的 Holder,MethodHandle 指向一个调用点真正执行的方法。

LambdaMetafactory

LambdaMetafactory 是 JDK 内部 CallSite 和 MethodHandle 绑定实现类。

LambdaMetafactory的关键方法

public static CallSite metafactory(MethodHandles.Lookup caller,String invokedName,MethodType invokedType,MethodType samMethodType,MethodHandle implMethod,MethodType instantiatedMethodType)throws LambdaConversionException {AbstractValidatingLambdaMetafactory mf;mf = new InnerClassLambdaMetafactory(caller, invokedType,invokedName, samMethodType,implMethod, instantiatedMethodType,false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);mf.validateMetafactoryArgs();return mf.buildCallSite();}
  • MethodHandles.Lookup caller – 调用者,也就是 Invokedynamic 指令运行的上下文,通常可以通过 Lookup#lookupClass() 获取。
  • String invokedName – Lambda 实现的接口的方法名称。
  • MethodType invokedType – 调用点的方法签名描述 ,
  • MethodType samMethodType – Lambda 实现的接口方法的签名描述 。(sam 就 single public abstract method 的缩写)
  • MethodHandle implMethod – 调用点的方法句柄。
  • MethodType instantiatedMethodType – 运行时调用点的方法签名描述。

参考:
https://zhuanlan.zhihu.com/p/28124632
https://www.jianshu.com/p/d74e92f93752
https://www.jianshu.com/p/7ef49246c176
https://www.cnblogs.com/wzqshb/p/16987548.html

http://www.lryc.cn/news/21375.html

相关文章:

  • 运动耳机推荐、最值得入手的运动耳机清单共享
  • c盘爆满--如何清理电脑C盘
  • Nginx配置web服务器及部署反向代理
  • mvvm和mvc
  • JavaScript while 循环
  • CMU15-445 Project.0总结
  • 计算机网络题库---错题本
  • 【react】react创建项目与引入AntD组件库:
  • hook与mixin
  • 【C语言】自定义类型
  • 没有上司的舞会(C++,树形DP)
  • 【java基础】static和final关键字的作用及其用法详解
  • #集成学习#:bagging、boosting、stacking和blending
  • NCRE计算机等级考试Python真题(一)
  • C#协变逆变
  • 算法设计与分析期末考试复习(四)
  • qsort函数排序数据 and 模拟实现qosrt函数(详解)
  • Mysql视图,存储过程,触发器,函数以及Mysql架构
  • 什么是线程死锁?如何解决死锁问题
  • C语言几种判断语句简述
  • 【python学习笔记】:SQL常用脚本(二)
  • 【Linux】进程地址空间
  • Qt音视频开发17-vlc内核回调拿图片进行绘制
  • 安装配置DHCP
  • MarkDown中写UML图的方法
  • Axure8设计—动态仪表盘
  • 【C++】类和对象的六个默认成员函数
  • 4、算法MATLAB---认识矩阵
  • vue3+rust个人博客建站日记2-确定需求
  • Linux安装云原生网关Kong/KongA