当前位置:网站首页>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
边栏推荐
- SecureCRTPortable的安装和使用(图文详解)
- 计网 | 【五 传输层、六 应用层】知识点及例题
- Why must a digital transformation strategy include continuous testing?
- Jenkins打包拉取不到最新的jar包
- 【ICCV 2019】特征超分检测:Towards Precise Supervision of Feature Super-Resolution for Small Object Detection
- 【ICLR 2021】半监督目标检测:Unbiased Teacher For Semi-Supervised Object Detection
- Filebeat自定义index和fields
- Great God detailed open source Buff gain Introduction 丨 Live
- Why must we move from Devops to bizdevops?
- Web host iptables firewall security script
猜你喜欢

Cv+deep learning network architecture pytoch recurrence series basenets (backbones) (I)

文件包含&条件竞争

TorchDrug--药物属性预测

Big God explains open source buff gain strategy live broadcast

Jenkins can't pull the latest jar package

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

漏洞扫描工具大全,妈妈再也不用担心我挖不到漏洞了

What is the difference between tolocal8bit and toutf8() in QT

Halcon知识:盘点一下计量对象【1】

Exness: the final value of US GDP unexpectedly accelerated to shrink by 1.6%
随机推荐
Qt:qaxobject operation Excel
好高的佣金,《新程序员》合伙人计划来袭,人人皆可参与
How to pass the PMP Exam quickly?
杰理之触摸按键识别流程【篇】
Halcon知识:盘点一下计量对象【1】
Is it safe to open an account for online stock trading!?
Is it safe to open an account in Guangzhou stock exchange by mobile phone?
Maya House Modeling
Kubevela 1.4: make application delivery safer, easier to use, and more transparent
计网 | 【五 传输层、六 应用层】知识点及例题
Torchdrug -- drug attribute prediction
Primary school, session 3 - afternoon: Web_ xxe
NLP skill tree learning route - (I) route overview
exness:流动性系列-流动性清洗和反转、决策区间
exness:美GDP终值意外加速萎缩1.6%
传输层 使用滑动窗口实现流量控制
Graduates
1045 error occurred in MySQL login. Modification method [easy to understand]
Notes on modification of Jerry's test box pairing software [chapter]
Playwright - 滚动条操作



