当前位置:网站首页>Lambda expression principle analysis and learning (June 23, 2022)
Lambda expression principle analysis and learning (June 23, 2022)
2022-06-30 20:19:00 【Ignorant programmer】
Lambda Expression principle analysis learning (2022.06.23)
The following code
public class LambdaTest {
public static void main(String[] args) {
Function<String,String> function = str -> str + test1();
String str = test2(function);
System.out.println(str);
}
public static String test1(){
return " Study ";
}
public static String test2( Function<String,String> function){
return function.apply(" I just ");
}
}
Personal guess
Initial conjecture jdk Is through grammar sugar , Compile time , Dynamically generates a Function Implementation class of interface , It receives the incoming parameters , And call
test1()
public class LambdaTest {
public static void main(String[] args) {
Function<String,String> function = new FunctionImpl();
String str = test2(function);
System.out.println(str);
}
public static String test1(){
return " Study ";
}
public static String test2( Function<String,String> function){
return function.apply(" I just ");
}
public class FunctionImpl implements Function<String,String>{
@Override
public String apply(String o) {
return o+test1();
}
}
}
In or directly through , Compile the way to generate anonymous inner classes , Direct implementation calls :
public static void main(String[] args) {
Function<String,String> function = new Function<String, String>() {
@Override
public String apply(String s) {
return s+test1();
}
};
String str = test2(function);
System.out.println(str);
}
public static String test1(){
return " Study ";
}
public static String test2( Function<String,String> function){
return function.apply(" I just ");
}
But in fact, it is not the above way .
Why not use anonymous inner classes or dynamically implemented classes , Because there are some shortcomings :
- Every anonymous inner class will be in
Compile timeCreate a correspondingclass file, stayRuntimeInevitably there will be loads 、 verification 、 Get ready 、 analysis 、 Initialization etc.Class loadingThe process .- Each call creates this
Anonymous inner class class Instance object of, Whether it's stateful ( External variables are used ) Or no state ( No external variables are used ) The inner class of .
Let's see below. JDK How to achieve Lambda Of expression
Compiled bytecode source code
Run the following code , Look at the compiled bytecode source code :
public class LambdaTest {
public static void main(String[] args) {
Function function = s -> s+test1();
String str = test2(function);
System.out.println(str);
}
public static String test1(){
return " Study ";
}
public static String test2( Function<String,String> function){
return function.apply(" I just ");
}
}
How to .class File directory Run the command :
javap -p LambdaMainOutput class All classes and members of the file , Get the output :
We can see that Lambda The expression in Java 8 First, a
Private static functions.
private static java.lang.Object lambda$main$0(java.lang.Object);When multiple... Are used in a method Lambda Expression will be incremented at the last index of the generated static function . Method parameters and return values correspond to functional interfaces
private static java.lang.Object lambda$main$1();
private static void lambda$main$2(java.lang.Object);
If we define a static function that is the same as the generated private function
public class LambdaTest {
public static void main(String[] args) {
Function function = s -> s+test1();
String str = test2(function);
System.out.println(str);
}
private static Object lambda$main$0(Object s){
return s;
}
public static String test1(){
return " Study ";
}
public static String test2( Function<String,String> function){
return function.apply(" I just ");
}
}
No errors will be reported during compilation , When running, it will report :
D:\my_project\nettyDemo\src\main\java\com\zhihao\LambdaTest.java:13:27 java: Symbol lambda$main$0(java.lang.Object) And com.zhihao.LambdaTest Medium compiler-synthesized Symbol conflictBecause there are two
lambda$main$0function , So when the code is running , I don't know which one to call , So you throw it wrong .So the question , Who calls this
lambda$main$0function
InvokeDynamic Instructions
Enter the command : javap -c -p LambdaTest View more detailed bytecode information
PS D:\my_project\nettyDemo\target\classes\com\zhihao> javap -c -p LambdaTest
Warning : Binary LambdaTest contain com.zhihao.LambdaTest
Compiled from "LambdaTest.java"
public class com.zhihao.LambdaTest {
public com.zhihao.LambdaTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokedynamic #2, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
5: astore_1
6: aload_1
7: invokestatic #3 // Method test2:(Ljava/util/function/Function;)Ljava/lang/String;
10: astore_2
11: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
14: aload_2
15: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
public static java.lang.String test1();
Code:
0: ldc #6 // String Study
2: areturn
public static java.lang.String test2(java.util.function.Function<java.lang.String, java.lang.String>);
Code:
0: aload_0
1: ldc #7 // String I just
3: invokeinterface #8, 2 // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
8: checkcast #9 // class java/lang/String
11: areturn
private static java.lang.Object lambda$main$0(java.lang.Object);
Code:
0: new #10 // class java/lang/StringBuilder
3: dup
4: invokespecial #11 // Method java/lang/StringBuilder."<init>":()V
7: aload_0
8: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
11: invokestatic #13 // Method test1:()Ljava/lang/String;
14: invokevirtual #14 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: invokevirtual #15 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
20: areturn
}
The code uses Lambda The statement of the expression is compiled into
invokedynamic #2, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;Point to constant pool #2 Locationinvokedynamic The location of the occurrence represents a dynamic call point ,invokedynamic The instruction is followed by a call point qualifier that points to the constant pool , This qualifier is resolved to a dynamic call point . According to this, you can find the corresponding dynamic call boot method java.lang.invoke.CallSite.
The details of JVM Virtual machine specification
It is used to delay Lambda Expression to bytecode conversion , Finally, this operation was postponed to runtime . let me put it another way , Used in this way invokedynamic, You can implement Lambda The bytecode generation of this part of the expression code is postponed until runtime . This design choice has brought a series of good results .
- Lambda The conversion from code block of expression to bytecode has changed from high-level strategy to pure implementation details . It can now change dynamically , Or be optimized in a future release 、 modify , And maintain the backward compatibility of bytecode .
- No extra cost , No additional fields , There is no need for static initialization , And if these are not used Lambda, It won't happen .
- For stateless non capture Lambda, We can create one Lambda Instance of object , Cache it , Then all accesses to the same object return the same content . This is a common use case , People are also Java 8 The usual way before ; such as , With static final Variable to declare a comparator instance .
- No additional performance overhead , Because these transformations are necessary , And the results are also linked , Only in Lambda When called for the first time, you need to convert . All subsequent calls can skip this step directly , Directly call the implementation of the previous link .
LambdaMetafactory # metafactory() ( file )
public static CallSite metafactory(MethodHandles.Lookup caller,
String invokedName,
MethodType invokedType,
MethodType samMethodType,
MethodHandle implMethod,
MethodType instantiatedMethodType)
throws LambdaConversionException {
AbstractValidatingLambdaMetafactory mf;
// It can be found in this function as Lambda Expression generates an inner class
mf = new InnerClassLambdaMetafactory(caller, invokedType,
invokedName, samMethodType,
implMethod, instantiatedMethodType,
false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
// verification
mf.validateMetafactoryArgs();
return mf.buildCallSite();
}
In use of Where the expression is Set a breakpoint , Then, you can debug the corresponding method of the above class by adding a breakpoint !
Parameters : caller、invokedName、invokedType All by jvm Generate ,
invokedName and invokedType They are called by dynamic call points NameAndType Generate ,
samMethodType and instantiatedMethodType The method descriptor that represents the functional interface ,
implMethod Above all , Refers to the user implemented Lambda Method , For this example :com.zhihao.LambdaTest.lambda$main$0(Object)Object/invokeStatic
Finally, the internal classes generated through memory , call
lambda$main$0Method
// Inner class
final class Lambda$1 {
@Override
public R apply(T t) {
return lambda$main$0(t);
}
}
summary :
- Lambda The expression in Java Finally compiled into
Private static functions,JDK End use invokedynamic Bytecode instruction call . - metafactory() Core to generate CallSite, This task mainly consists of InnerClassLambdaMetafactory Of buildCallSite() complete ,buildCallSite() Continue to call spinInnerClass() function ,spinInnerClass Function uses bytecode tool to generate a class in memory .
1
边栏推荐
- CADD course learning (1) -- basic knowledge of drug design
- 项目经理不应该犯的错误
- Application of JDBC in performance test
- Lambda 表达式原理分析学习(2022.06.23)
- 将秒数转换为**小时**分钟
- CADD course learning (2) -- target crystal structure information
- The Commission is so high that everyone can participate in the new programmer's partner plan
- 神经网络入门(上)
- Client request external interface standard processing method
- Data intelligence - dtcc2022! China database technology conference is about to open
猜你喜欢

GeoServer安装

The prospectus of pelt medical was "invalid" for the second time in the Hong Kong stock exchange, and the listing plan was substantially delayed

Lambda 表达式原理分析学习(2022.06.23)

25:第三章:开发通行证服务:8:【注册/登录】接口:接收并校验“手机号和验证码”参数;(重点需要知道【利用redis来暂存数据,获取数据的】的应用场景)(使用到了【@Valid注解】参数校验)

分析超700万个研发需求发现,这八大编程语言才是行业最需要的

Maya House Modeling
Django上传excel表格并将数据写入数据库的详细步骤

以全栈全功能解决方案,应对多样工具复杂环境DevOps落地难题

如何快速通过PMP考试?

Primary school, session 3 - afternoon: Web_ sessionlfi
随机推荐
传输层 使用滑动窗口实现流量控制
Pytorch implements the calculation of flops and params
Tensorflow2.4 implementation of repvgg
[try to hack] windows system account security
项目经理是领导吗?可以批评指责成员吗?
25: Chapter 3: developing pass service: 8: [registration / login] interface: receiving and verifying "mobile number and verification code" parameters; (it is important to know the application scenario
The Commission is so high that everyone can participate in the new programmer's partner plan
Introduction to neural network (Part 1)
Client请求外部接口标准处理方式
Heartbeat 与DRBD 配置过程
25:第三章:开发通行证服务:8:【注册/登录】接口:接收并校验“手机号和验证码”参数;(重点需要知道【利用redis来暂存数据,获取数据的】的应用场景)(使用到了【@Valid注解】参数校验)
昨晚 Spark Summit 重要功能发布全在这里(附超清视频)
新出生的机器狗,打滚1小时后自己掌握走路,吴恩达开山大弟子最新成果
exness:美GDP终值意外加速萎缩1.6%
Jerry's touch key recognition process [chapter]
Audio and video architecture construction in the super video era | science and Intel jointly launched the second season of "architect growth plan"
CADD课程学习(1)-- 药物设计基础知识
杰理之检测灵敏度级别确定【篇】
Big God explains open source buff gain strategy live broadcast
Kubevela 1.4: make application delivery safer, easier to use, and more transparent


