2016-11-26 7 views
5

मैं नीचे जावा प्रोग्राम में एक कार्यात्मक इंटरफ़ेस को लागू करने के लिए लैम्ब्डा का उपयोग कर रहा हूं। जब लैम्ब्डा को सामान्य विधि के लिए तर्क के रूप में पारित किया जाता है, तो संकलक एक "असंगत प्रकार" त्रुटि को झुकाता है क्योंकि यह अनुमान लगाता है कि लैम्ब्डा Func < आकार > इंटरफ़ेस लागू करता है, जिसमें कंपाइलर लैम्ब्डा पैरामीटर ("चीज़") की व्याख्या करता है प्रकार का आकार होने पर लैम्ब्डा इसे एक विधि (टेस्टराउंड) में पास करने का प्रयास करता है जिसके लिए राउंड प्रकार के तर्क की आवश्यकता होती है। यह त्रुटि मुझे समझ में आता है।लैम्बडा के लिए टाइप अनुमान क्यों विफल रहता है, लेकिन समकक्ष विधि संदर्भ के लिए सफल होता है?

लेकिन समकक्ष विधि संदर्भ एक त्रुटि संदेश को उत्तेजित नहीं करता है। मैं गलत धारणा के तहत था कि एक लैम्ब्डा और एक विधि संदर्भ जो उस लैम्ब्डा को प्रतिस्थापित कर सकता था, विनिमयशील था। यहाँ, ऐसा नहीं है।

public class Main 
{ 
    public static void main(String... args) 
    { 
     methodB(thing -> Main.testRound(thing)); // incompatible types 
     methodB(Main::testRound);    // no problem here 
    } 

    static <T extends Shape> void methodB(Func<T> function) 
    { 
    } 

    static boolean testRound(Round thing) 
    { 
     return true; 
    } 
} 

interface Func<T> 
{ 
    boolean test(T ob); 
} 

class Shape 
{ 
} 

class Round extends Shape 
{ 
} 

लैम्बडा विफल होने पर विधि संदर्भ सफल क्यों होता है?

अद्यतन

विन्स Emigh जवाब है, जो मैं, के रूप में स्वीकार कर लिया नीचे चिह्नित किया है पाया।

// Use a type witness. 

Main.<Round>methodB(thing -> testRound(thing)); 

// Make the lambda's argument type explicit. 

methodB((Round thing) -> testRound(thing)); 

// Cast the argument. 

methodB(thing -> testRound((Round)thing)); 

// Store the lambda reference in a Func<Round> variable. 

Func<Round> lambda = thing -> testRound(thing); 
methodB(lambda); 

मैं किसी भी नहीं दिख रहा है: हालांकि यह मेरे सवाल का हिस्सा नहीं है, यहाँ तथ्य यह है कि लैम्ब्डा ही प्रकार Func<Shape> अगर एक वास्तव में lambdas के प्रयोग पर फंस गईं के रूप में किया जा रहा है मान लिया जाता है के आसपास काम करने के लिए चार तरीके हैं विधि संदर्भ में इनमें से किसी एक को प्राथमिकता देने का कारण, जब तक कि कोई ऐसा महसूस न करे कि लैम्ब्डा थोड़ा कम घना होता है (और, शायद, थोड़ा और पठनीय)। लेकिन, अगर आप उन्हें चाहते हैं तो वे वहां हैं।

+1

एकमात्र धारणा जिसे मैं कर सकता हूं (जिसे मैं अभी भी एक खिंचाव महसूस करता हूं) है: * अलग-अलग समय पर अनुमान लग रहा है *। लैम्ब्डा के साथ, 'चीज' को 'टी विस्तारित करता है' के रूप में देखा जाता है (जैसे ही 'चीज' घोषित किया जाता है) जबकि 'testRound' को स्पष्ट रूप से' राउंड 'की आवश्यकता होती है, जिससे त्रुटि होती है। विधि संदर्भ का उपयोग करते समय, तर्क को 'राउंड' के रूप में देखा जाता है क्योंकि इसे '(टी चीज) 'के बजाय' मुख्य :: टेस्टराउंड' से अनुमानित किया जा रहा है। उम्मीद है कि यह समझ में आता है, और ध्यान रखें कि दस्तावेज के बजाय अनुभव पर आधारित संदेह है। मैं इसे बेहतर (अधिक आधिकारिक) उत्तर –

+0

@VinceEmigh की उम्मीद में देख रहा हूं, मेरे पास समान चेतावनी के साथ कुछ समान विचार थे। अगर आपको कुछ मिलता है तो कृपया मुझे बताएं। यह निश्चित रूप से परेशान है। –

+0

शायद यह: पहले आमंत्रण में, लैम्ब्डा 'Func ' इंटरफ़ेस लागू करता है, जिससे संकलक यह बताता है कि लैम्ब्डा का तर्क 'आकार' प्रकार का है, और यह 'आकार' पास करने के लिए एक संकलित-समय त्रुटि है 'test'ound 'करने के लिए। दूसरे आमंत्रण में, कार्यान्वयन के लिए तर्क प्रकार विधि हस्ताक्षर से _copied_ है, यहां, 'गोल चीज़' है। (जेएलएस 15.12 देखें।3, "संकलन-समय पैरामीटर प्रकार संकलन-समय घोषणा के औपचारिक मानकों के प्रकार हैं [।]") वास्तव में, इसका मतलब है अन्यथा समान लैम्ब्डा और सदस्य संदर्भ _not_ विनिमय योग्य हैं। –

उत्तर

1

JLS §15.13.2 से:

एक लैम्ब्डा अभिव्यक्ति के विपरीत, एक विधि संदर्भ में एक सामान्य समारोह प्रकार के साथ अनुकूल हो सकता है (जो है, एक समारोह प्रकार पैरामीटर टाइप छोटा है)। ऐसा इसलिए है क्योंकि लैम्ब्डा अभिव्यक्ति को प्रकार पैरामीटर घोषित करने में सक्षम होना आवश्यक है, और कोई वाक्यविन्यास इसका समर्थन नहीं करता है; जबकि एक विधि संदर्भ के लिए, ऐसी कोई घोषणा आवश्यक नहीं है।

लैम्ब्डा अभिव्यक्ति एक त्रुटि उत्पन्न करती है क्योंकि निर्दिष्ट कोई तर्क तर्क नहीं है। यह T को Shape के रूप में संकलित करने के लिए कारण बनता है (जैसा कि आपकी पोस्ट में उल्लिखित है), क्योंकि तर्क के प्रकार का अनुमान लगाने में कुछ भी नहीं है।

विधि संदर्भों के लिए, क्योंकि विधि के पैरामीटर से प्रकार का अनुमान लगाया जा सकता है, ऊपर दिए गए जेएलएस कथन में उल्लिखित अनुसार कोई स्पष्ट प्रकार तर्क की आवश्यकता नहीं है।

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

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