2015-09-21 5 views
19

मैं जावा 8. की नई सुविधाओंक्या जावा 8 विधि संदर्भ के लिए फ्लाई पर इंटरफेस लागू कर सकता है?

मैं अलग उदाहरण के साथ खेल रहा हूँ जानने के लिए और मैं एक अजीब व्यवहार पाया है:

public static void main(String[] args) {  
    method(Test::new); 
} 
static class Test{ 
} 

private static void method(Supplier<Test> testSupplier){ 
    Test test = testSupplier.get(); 
} 

इस कोड को सफलतापूर्वक संकलित लेकिन मैं पता नहीं यह कैसे काम करता है।

Test::new प्रदायक के रूप में स्वीकार्य क्यों है?

प्रदायक इंटरफ़ेस बहुत सरल दिखता है:

@FunctionalInterface 
public interface Supplier<T> {  
    T get(); 
} 
+2

गतिशील रूप से कार्यान्वित करने के लिए किस तरह का होता है AFAIK यह जानवर है: ['java.lang.invoke.LambdaMetafactory'] (https://docs.oracle.com/javase/8/docs/api/java/lang/ invoke/LambdaMetafactory.html) – zapl

+3

ध्यान दें कि "खाली" वर्ग घोषणा, जैसे कि आपके 'कक्षा टेस्ट' के लिए, निहित रूप से नो-एर्ग कन्स्ट्रक्टर है। यही कारण है कि आप 'नया टेस्ट() 'लिख सकते हैं और इसे काम कर सकते हैं, किसी भी इस कन्स्ट्रक्टर के लिए लैम्ब्डा या विधि संदर्भ क्यों काम करता है। –

+0

@Sotirios Delimanolis शायद लिंक किए गए प्रश्न पर पहली टिप्पणी अधिक प्रासंगिक – gstackoverflow

उत्तर

19

Supplier इंटरफ़ेस एक एकल (कार्यात्मक) विधि है कि है:

the Java Tutorial, से विधि संदर्भ के चार प्रकार के होते हैं

  • नहीं कोई पैरामीटर ले करता है;
  • कोई ऑब्जेक्ट देता है।

इसलिए, उन दो बिंदुओं का अनुपालन करने वाली कोई भी विधि Supplier के कार्यात्मक अनुबंध का अनुपालन करती है (क्योंकि विधियों का एक ही हस्ताक्षर होगा)।

यहां, प्रश्न में विधि एक विधि संदर्भ है। इसमें कोई पैरामीटर नहीं होता है और Test का नया उदाहरण देता है। इस लैम्ब्डा अभिव्यक्ति के लिए वाक्यात्मक चीनी में

method(() -> new Test()); 

Test::new: आप करने के लिए इसे फिर से लिखने सकता है।

+0

है, इस प्रकार यदि मेरे विषय से प्रश्न का उत्तर दें - हां, गति संदर्भ इंटरफ़ेस कार्यान्वयन के लिए विधि संदर्भ का आविष्कार किया गया था। – gstackoverflow

3

यह एक Function हो सकता है, बल्कि एक सप्लायर से, अगर एक बहस की आवश्यकता है। लेकिन विधि संदर्भ रचनाकारों को उसी तरीके से संदर्भित कर सकते हैं जैसे वे विधियों का संदर्भ देते हैं; उनके पास सिर्फ एक मजाकिया नाम है (new)।

 
Kind        Example 
------------------------------- ------------------------------------ 
Reference to a static method  ContainingClass::staticMethodName 
Reference to an instance method containingObject::instanceMethodName 
of a particular object 
Reference to an instance method ContainingType::methodName 
of an arbitrary object of a 
particular type 
Reference to a constructor  ClassName::new 
11

Test::new एक विधि संदर्भ है। एक नया स्पष्टीकरण जोड़ने के बजाय method references के लिए ट्यूटोरियल को देखने के लायक है क्योंकि यह उन्हें बहुत अच्छी तरह से समझाता है।

अपने सवाल का सीधा जवाब है कि Supplier एक कार्यात्मक इंटरफ़ेस है - जिसका अर्थ यह एक गैर डिफ़ॉल्ट विधि है। Test के लिए कन्स्ट्रक्टर बिल्कुल वही हस्ताक्षर है (कोई तर्क नहीं, Test देता है) और इसलिए अज्ञात Supplier बनाने के लिए सीधे संदर्भित किया जा सकता है।

विधि संदर्भों के चार स्वाद हैं: उन सभी को समझने के लिए ट्यूटोरियल देखें।

+0

इस प्रकार यह सुविधा अनुमति देती है कि पुराने वर्ग नए बनाए गए इंटरफ़ेस को कार्यान्वित कर सकें। वाह! – gstackoverflow

+1

@gstackoverflow हाँ यह सही है। जब तक हस्ताक्षर मिलान होते हैं तब तक आप इंटरफ़ेस का उदाहरण बनाने के लिए विधि का संदर्भ ले सकते हैं। जब अच्छी तरह से उपयोग किया जाता है तो यह कोड की पठनीयता में काफी सुधार कर सकता है। – sprinter

संबंधित मुद्दे