आप SE8 15.27 का उल्लेख करने की जरूरत है:
15.27.3। एक लैम्ब्डा अभिव्यक्ति
एक लैम्ब्डा अभिव्यक्ति एक काम संदर्भ में संगत है, मंगलाचरण संदर्भ, या एक लक्ष्य प्रकार टी के साथ संदर्भ कास्टिंग करता है, तो टी एक कार्यात्मक इंटरफ़ेस प्रकार (§9.8) और प्रकार अभिव्यक्ति के साथ अनुकूल है जमीनी लक्ष्य टी
क्रम से प्राप्त प्रकार invokedynamic
के साथ प्रयोग के मुश्किल चीजों से निपटने में समारोह प्रकार। चलो कुछ कोड की जांच:
import java.util.function.*;
class R implements Runnable {
public void run() { System.out.println("there"); }
}
public class L {
public static void execute(Runnable r) {
System.out.println(r.getClass());
r.run();
}
public static void main(String []a) {
execute(new R()); // subclass
execute(new Runnable() { // anonymous subclass
public void run() { System.out.println("elsewhere"); }
});
execute(() -> System.out.println("here")); // lambda
}
}
निष्पादन देता है:
> java L
class R
there
class L$1
elsewhere
class L$$Lambda$1/791452441
here
पहले दो के लिए वहाँ (दिए गए क्रम में) कोई आश्चर्य की बात, वस्तु विधि execute
द्वारा प्राप्त है के वर्ग है R
(Runnable
का उप प्रकार), L$1
(Runnable
का अज्ञात उप प्रकार, और L$$Lambda$1/791452441
(Runnable
का उप प्रकार लैम्ब्डा से रन टाइम पर बनाया गया)।ध्यान दें कि लैम्ब्डा के मामले में .class
फ़ाइल नहीं है, प्रकार विशेष निर्माण द्वारा रनटाइम पर बनाया गया है। के बाईटकोड जांच:
> javap -c -v L
Classfile /private/tmp/L.class
Last modified 1 août 2017; size 1234 bytes
MD5 checksum 9680a2bc143d25344979bae00fff3db7
Compiled from "L.java"
public class L
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #15.#28 // java/lang/Object."<init>":()V
#2 = Fieldref #29.#30 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #15.#31 // java/lang/Object.getClass:()Ljava/lang/Class;
#4 = Methodref #32.#33 // java/io/PrintStream.println:(Ljava/lang/Object;)V
#5 = InterfaceMethodref #34.#35 // java/lang/Runnable.run:()V
#6 = Class #36 // R
#7 = Methodref #6.#28 // R."<init>":()V
#8 = Methodref #14.#37 // L.execute:(Ljava/lang/Runnable;)V
#9 = Class #38 // L$1
#10 = Methodref #9.#28 // L$1."<init>":()V
#11 = InvokeDynamic #0:#43 // #0:run:()Ljava/lang/Runnable;
#12 = String #44 // here
#13 = Methodref #32.#45 // java/io/PrintStream.println:(Ljava/lang/String;)V
#14 = Class #46 // L
#15 = Class #47 // java/lang/Object
#16 = Utf8 InnerClasses
#17 = Utf8 <init>
#18 = Utf8 ()V
#19 = Utf8 Code
#20 = Utf8 LineNumberTable
#21 = Utf8 execute
#22 = Utf8 (Ljava/lang/Runnable;)V
#23 = Utf8 main
#24 = Utf8 ([Ljava/lang/String;)V
#25 = Utf8 lambda$main$0
#26 = Utf8 SourceFile
#27 = Utf8 L.java
#28 = NameAndType #17:#18 // "<init>":()V
#29 = Class #48 // java/lang/System
#30 = NameAndType #49:#50 // out:Ljava/io/PrintStream;
#31 = NameAndType #51:#52 // getClass:()Ljava/lang/Class;
#32 = Class #53 // java/io/PrintStream
#33 = NameAndType #54:#55 // println:(Ljava/lang/Object;)V
#34 = Class #56 // java/lang/Runnable
#35 = NameAndType #57:#18 // run:()V
#36 = Utf8 R
#37 = NameAndType #21:#22 // execute:(Ljava/lang/Runnable;)V
#38 = Utf8 L$1
#39 = Utf8 BootstrapMethods
#40 = MethodHandle #6:#58 // invokestatic java/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;
#41 = MethodType #18 // ()V
#42 = MethodHandle #6:#59 // invokestatic L.lambda$main$0:()V
#43 = NameAndType #57:#60 // run:()Ljava/lang/Runnable;
#44 = Utf8 here
#45 = NameAndType #54:#61 // println:(Ljava/lang/String;)V
#46 = Utf8 L
#47 = Utf8 java/lang/Object
#48 = Utf8 java/lang/System
#49 = Utf8 out
#50 = Utf8 Ljava/io/PrintStream;
#51 = Utf8 getClass
#52 = Utf8 ()Ljava/lang/Class;
#53 = Utf8 java/io/PrintStream
#54 = Utf8 println
#55 = Utf8 (Ljava/lang/Object;)V
#56 = Utf8 java/lang/Runnable
#57 = Utf8 run
#58 = Methodref #62.#63 // java/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;
#59 = Methodref #14.#64 // L.lambda$main$0:()V
#60 = Utf8 ()Ljava/lang/Runnable;
#61 = Utf8 (Ljava/lang/String;)V
#62 = Class #65 // java/lang/invoke/LambdaMetafactory
#63 = NameAndType #66:#69 // 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;
#64 = NameAndType #25:#18 // lambda$main$0:()V
#65 = Utf8 java/lang/invoke/LambdaMetafactory
#66 = Utf8 metafactory
#67 = Class #71 // java/lang/invoke/MethodHandles$Lookup
#68 = Utf8 Lookup
#69 = Utf8 (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;
#70 = Class #72 // java/lang/invoke/MethodHandles
#71 = Utf8 java/lang/invoke/MethodHandles$Lookup
#72 = Utf8 java/lang/invoke/MethodHandles
{
public L();
descriptor:()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 9: 0
public static void execute(java.lang.Runnable);
descriptor: (Ljava/lang/Runnable;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: invokevirtual #3 // Method java/lang/Object.getClass:()Ljava/lang/Class;
7: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
10: aload_0
11: invokeinterface #5, 1 // InterfaceMethod java/lang/Runnable.run:()V
16: return
LineNumberTable:
line 11: 0
line 12: 10
line 13: 16
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: new #6 // class R
3: dup
4: invokespecial #7 // Method R."<init>":()V
7: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
10: new #9 // class L$1
13: dup
14: invokespecial #10 // Method L$1."<init>":()V
17: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
20: invokedynamiC#11, 0 // InvokeDynamiC#0:run:()Ljava/lang/Runnable;
25: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
28: return
LineNumberTable:
line 15: 0
line 16: 10
line 19: 20
line 20: 28
}
SourceFile: "L.java"
InnerClasses:
statiC#9; //class L$1
public static final #68= #67 of #70; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #40 invokestatic java/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;
Method arguments:
#41()V
#42 invokestatic L.lambda$main$0:()V
#41()V
पहले दिलचस्प हिस्सा main
का कोड है:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: new #6 // class R
3: dup
4: invokespecial #7 // Method R."<init>":()V
7: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
10: new #9 // class L$1
13: dup
14: invokespecial #10 // Method L$1."<init>":()V
17: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
20: invokedynamiC#11, 0 // InvokeDynamiC#0:run:()Ljava/lang/Runnable;
25: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
28: return
आप देख सकते हैं के रूप में वहाँ इंटरफ़ेस का स्पष्ट कार्यान्वयन या अनाम एक के बीच में कोई अंतर नहीं है। आखिरी में केवल कक्षा नामकरण ट्रिकरी (L$1
) शामिल है, लेकिन दोनों का उपयोग उसी तरह किया जाता है, invokestatic
के माध्यम से।
दिलचस्प मामला तीसरा (लैम्ब्डा एक) है जिसमें invokedynamic
और फिर invokestatic
शामिल है। ध्यान दें कि invokestatic
दो पिछली कॉल (विधि run
) में समान विधि को कॉल करता है।
मोटे तौर पर, पहली बार invokedynamic
कहा जाता है एक बूटस्ट्रैप विधि निर्माण करने के लिए कहा जाता है एक CallSite
(CallSite in Java API देखें) जो तब लैम्ब्डा का कोड निष्पादित करने के लिए आगे इस्तेमाल किया जाएगा।
BootstrapMethods:
0: #40 invokestatic java/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;
Method arguments:
#41()V
#42 invokestatic L.lambda$main$0:()V
#41()V
और कोड कॉल साइट से रेफ़र किया: यहां बूटस्ट्रैप कॉल देखें
#41 = MethodType #18 // ()V
#42 = MethodHandle #6:#59 // invokestatic L.lambda$main$0:()V
#43 = NameAndType #57:#60 // run:()Ljava/lang/Runnable;
#44 = Utf8 here
#45 = NameAndType #54:#61 // println:(Ljava/lang/String;)V
#46 = Utf8 L
#47 = Utf8 java/lang/Object
#48 = Utf8 java/lang/System
#49 = Utf8 out
#50 = Utf8 Ljava/io/PrintStream;
#51 = Utf8 getClass
#52 = Utf8 ()Ljava/lang/Class;
#53 = Utf8 java/io/PrintStream
#54 = Utf8 println
#55 = Utf8 (Ljava/lang/Object;)V
#56 = Utf8 java/lang/Runnable
#57 = Utf8 run
वहां * कक्षाएं हैं। यह धुआं और दर्पण है। – user2864740
ऐसा इसलिए है क्योंकि JVM लैम्बडा अभिव्यक्ति/विधि संदर्भ अभिव्यक्ति के पुल विधियों के लिए स्मृति में 'उपभोक्ता' का उप-वर्ग बनायेगा। –
@ होली-जावा मुझे किसी भी '.class' फ़ाइल को क्लास पथ से संबंधित नहीं मिला है। क्या आप कृपया संक्षिप्त कर सकते हैं। स्मृति में – TheCurious