当前位置:网站首页>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
边栏推荐
- How to pass the PMP Exam quickly?
- Ten percent of the time, the tar command can't parse the English bracket "()" when decompressing the file
- Django上传excel表格并将数据写入数据库的详细步骤
- QT :QAxObject操作Excel
- Openfire solves the problem of Chinese garbled code after using MySQL database
- 1045 error occurred in MySQL login. Modification method [easy to understand]
- Heartbeat uses NFS to make MySQL highly available based on CRM
- Cv+deep learning network architecture pytoch recurrence series basenets (backbones) (I)
- NLP 论文领读|文本生成模型退化怎么办?SimCTG 告诉你答案
- Enterprise middle office planning and it architecture microservice transformation
猜你喜欢

Why should offline stores do new retail?

The Commission is so high that everyone can participate in the new programmer's partner plan

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

Audio and video architecture construction in the super video era | science and Intel jointly launched the second season of "architect growth plan"

建立自己的网站(20)

NLP paper lead reading | what about the degradation of text generation model? Simctg tells you the answer

To eliminate bugs, developers must know several bug exploration and testing artifacts.

操作系统面试题汇总(不定期更新)

Enterprise middle office planning and it architecture microservice transformation

数据智能——DTCC2022!中国数据库技术大会即将开幕
随机推荐
Jerry's determination of detection sensitivity level [chapter]
Client request external interface standard processing method
Go language learning tutorial (13)
操作系统面试题汇总(不定期更新)
Cv+deep learning network architecture pytoch recurrence series basenets (backbones) (I)
以全栈全功能解决方案,应对多样工具复杂环境DevOps落地难题
RP prototype resource sharing - shopping app
如何快速通过PMP考试?
杰理之关于长按复位【篇】
Great God detailed open source Buff gain Introduction 丨 Live
Why must we move from Devops to bizdevops?
Qt:qaxobject operation Excel
Ten percent of the time, the tar command can't parse the English bracket "()" when decompressing the file
Spark - 一文搞懂 Partitioner
杰理之关于长按开机检测抬起问题【篇】
CADD课程学习(2)-- 靶点晶体结构信息
Jerry's touch key recognition process [chapter]
【ICCV 2019】特征超分检测:Towards Precise Supervision of Feature Super-Resolution for Small Object Detection
Heartbeat and DRBD configuration process
Why should offline stores do new retail?



