当前位置:网站首页>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
边栏推荐
- mysql主从同步
- Static classes use @resource annotation injection
- CADD课程学习(1)-- 药物设计基础知识
- 传输层 使用滑动窗口实现流量控制
- 静态类使用@Resource注解注入
- Smarter! Airiot accelerates the upgrading of energy conservation and emission reduction in the coal industry
- Data intelligence - dtcc2022! China database technology conference is about to open
- Openfire在使用MySQL数据库后的中文乱码问题解决
- DEX file parsing - Method_ IDS resolution
- Primary school, session 3 - afternoon: Web_ xxe
猜你喜欢

4.3-inch touch screen 12 channel control port programmable network central control supports mutual backup of 5 central control hosts

DEX文件解析 - method_ids解析

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

CV+Deep Learning——网络架构Pytorch复现系列——basenets(BackBones)(一)

How unity pulls one of multiple components

Jenkins can't pull the latest jar package

Tensorflow2.4 implementation of repvgg

1、生成对抗网络入门

MySQL master-slave synchronization

CADD course learning (2) -- target crystal structure information
随机推荐
Maya House Modeling
QT qstringlist usage
Application of JDBC in performance test
Filebeat custom indexes and fields
GeoServer安装
Jenkins打包拉取不到最新的jar包
新出生的机器狗,打滚1小时后自己掌握走路,吴恩达开山大弟子最新成果
Smarter! Airiot accelerates the upgrading of energy conservation and emission reduction in the coal industry
C language: hashtable
分析超700万个研发需求发现,这八大编程语言才是行业最需要的
大神详解开源 BUFF 增益攻略丨直播
Static classes use @resource annotation injection
Graduates
Torchdrug -- drug attribute prediction
Summary of operating system interview questions (updated from time to time)
TorchDrug--药物属性预测
VB的基本语法
Filebeat自定义index和fields
Great God detailed open source Buff gain Introduction 丨 Live
昨晚 Spark Summit 重要功能发布全在这里(附超清视频)



