बूटस्ट्रैप विधि है, जो आप lambdaType
नामित करने के लिए तीसरा तर्क, लागू प्रकार जुड़े invokedynamic
की है निर्देश (आमतौर पर जेवीएम द्वारा भरा जाता है)। यह अर्थात् बूटस्ट्रैप विधि द्वारा परिभाषित किया गया है और LambdaMetaFactory
के मामले में, यह कार्यात्मक इंटरफ़ेस को रिटर्न प्रकार (ऑब्जेक्ट का निर्माण करने के प्रकार) के रूप में निर्दिष्ट करता है और पैरामीटर प्रकार के रूप में कैप्चर करने के लिए मान (मूल्यों का प्रकार कब उपभोग करता है एक लैम्ब्डा उदाहरण का निर्माण)।
तो आदेश this
पर कब्जा करने में, आप अपने लागू प्रकार के this
के प्रकार जोड़ सकते हैं और this
invokeExact
कॉल करने के लिए एक तर्क के रूप पारित करने के लिए है:
public class Test {
public static void main(String... arg) throws Throwable {
System.out.println(new Test().foo().getAsInt());
}
public IntSupplier foo() throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(int.class),
invokedType = MethodType.methodType(IntSupplier.class, Test.class);
MethodHandle methodHandle = lookup.findVirtual(getClass(), "fortyTwo", methodType);
CallSite callSite = LambdaMetafactory.metafactory(lookup, "getAsInt",
invokedType, methodType, methodHandle, methodType);
return (IntSupplier) callSite.getTarget().invokeExact(this);
}
public int fortyTwo() {
return 42;
}
}
आप अधिक मान कैप्चर करना चाहते हैं, तो आप उन्हें सही क्रम में हस्ताक्षर में जोड़ना होगा। ,
public class Test {
public static void main(String... arg) throws Throwable {
System.out.println(new Test().foo(100).getAsInt());
}
public IntSupplier foo(int capture) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(int.class, int.class),
functionType = MethodType.methodType(int.class),
invokedType = MethodType.methodType(IntSupplier.class, Test.class, int.class);
MethodHandle methodHandle=lookup.findVirtual(getClass(),"addFortyTwo",methodType);
CallSite callSite = LambdaMetafactory.metafactory(lookup, "getAsInt",
invokedType, functionType, methodHandle, functionType);
return (IntSupplier) callSite.getTarget().invokeExact(this, capture);
}
public int addFortyTwo(int valueToAdd) {
return 42+valueToAdd;
}
}
लक्ष्य विधि this
प्रकार से मिलकर एक हस्ताक्षर करना होगा static
यदि नहीं, तो सभी पैरामीटर प्रकार के द्वारा पीछा किया: उदाहरण, एक और int
मूल्य पर कब्जा करने की। कैप्चर वैल्यू इस हस्ताक्षर के प्रकार को बाएं से दाएं और शेष पैरामीटर प्रकारों के लिए मैप करेगा, यदि कोई हो, तो कार्यात्मक हस्ताक्षर में योगदान दें, इसलिए interface
विधि के पैरामीटर प्रकारों से मेल खाना होगा।
यह दर्शाता है कि जब कोई कब्जा मूल्य नहीं होता है और लक्ष्य विधि static
नहीं है, तो विधि रिसीवर प्रकार कार्यात्मक हस्ताक्षर के पहले प्रकार से संबद्ध हो सकता है, जैसा कि ToIntFunction<String> f=String::length;
में है।
मुझे लगता है कि यह समझने के उद्देश्य से है कि लैम्बडा आंतरिक रूप से कैसे काम करते हैं, क्योंकि अन्यथा आप नए इंट्सप्लियर() {...}; 'बिना किसी जादू के' वापस लौटेंगे। – immibis
जो मुझे समझ में नहीं आता है, वह "सामान्य रूप से आभासी नहीं होगा" टिप्पणी है। – Holger