2015-03-16 4 views
15

java-8 सिंटैक्स के बारे में सरल प्रश्न। क्यों JLS-8 की तरह इस तरह के भाव को प्रतिबंधित करता है:मैं ऑब्जेक्ट प्रकार के चर के लिए सीधे विधि संदर्भ क्यों निर्दिष्ट नहीं कर सकता?

Object of_ref = Stream::of; // compile-time error 

और जैसे ही कुछ अनुमति देते हैं:

java.util.function.Function of_ref = Stream::of; 
Object obj = of_ref; // compiles ok 

?

+4

आपके पहले असम्बद्ध स्निपेट में आप 'of_ref' में संग्रहीत होने की अपेक्षा करेंगे? संदर्भित ठोस प्रकार का ठोस प्रकार क्या होगा? –

उत्तर

7

से प्राप्त ग्राउंड लक्ष्य प्रकार का फ़ंक्शन प्रकार ऐसा इसलिए है क्योंकि एक विधि संदर्भ या लैम्ब्डा अभिव्यक्ति का लक्ष्य प्रकार एक कार्यात्मक इंटरफ़ेस होना चाहिए। उस पर आधारित, रनटाइम दिए गए कार्यात्मक इंटरफ़ेस के कार्यान्वयन प्रदान करने वाले वर्ग का एक उदाहरण बनाएगा। abstract अवधारणा के रूप में लैम्बडा या विधि संदर्भों के बारे में सोचें। इसे एक कार्यात्मक इंटरफ़ेस प्रकार में असाइन करना इसे एक ठोस अर्थ देता है।

इसके अलावा, एक विशेष लैम्ब्डा या विधि संदर्भ, इसके लक्ष्य प्रकार के रूप में कई कार्यात्मक इंटरफेस हो सकता है। उदाहरण के लिए, निम्नलिखित lamda पर विचार करें:

int x = 5; 
FunctionalInterface func = (x) -> System.out.println(x); 

यह लैम्ब्डा x के Consumer है। इसके अलावा, निम्नलिखित हस्ताक्षर वाले एक अमूर्त विधि वाला कोई इंटरफ़ेस:

public abstract void xxx(int value); 

लक्ष्य प्रकार के रूप में उपयोग किया जा सकता है। तो, यदि आप लैम्ब्डा को Object प्रकार पर निर्दिष्ट करते हैं, तो आप किस इंटरफ़ेस को रनटाइम लागू करना चाहते हैं? यही कारण है कि आपको स्पष्ट रूप से लक्ष्य प्रकार के रूप में एक कार्यात्मक इंटरफ़ेस प्रदान करना होगा।

अब, एक बार आप एक उदाहरण पकड़े एक कार्यात्मक इंटरफ़ेस संदर्भ मिला है, तो आप इसे (Object सहित) किसी भी सुपर संदर्भ के लिए प्रदान कर सकते हैं

+0

धन्यवाद, लेकिन यह मेरे लिए अलौकिक लगता है: मैं अपने 'ओबीजे' को वापस 'फंक्शन' में परिवर्तित कर सकता हूं और 'लागू() 'का आह्वान कर सकता हूं, इसलिए हम विधि संदर्भ पुनर्प्राप्त करते समय इसे सीधे नहीं कर सकते हैं? – Andremoniy

+2

@Andremoniy 'obj' को वापस' फ़ंक्शन 'में बदलने के लिए, आपको पहले' ऑब्जेक्ट 'दाएं बनाना होगा? उस 'ऑब्जेक्ट' का प्रकार क्या होगा? –

+0

आह, ठीक है, मैं आपके तर्क को समझता हूं। – Andremoniy

8

Object एक कार्यात्मक इंटरफेस नहीं है और एक विधि संदर्भ केवल एक कार्यात्मक इंटरफ़ेस को असाइन किया जा सकता है। उदाहरण JLS #15.13.2

एक विधि संदर्भ अभिव्यक्ति एक काम संदर्भ, मंगलाचरण संदर्भ, या एक लक्ष्य प्रकार टी के साथ कास्टिंग संदर्भ में संगत है अगर टी एक कार्यात्मक इंटरफ़ेस प्रकार (§9.8) है और अभिव्यक्ति के साथ अनुकूल है के लिए देखें टी

+0

धन्यवाद, लेकिन मैं पूछता हूं कि मैं इस संदर्भ को 'ऑब्जेक्ट' को सीधे क्यों निर्दिष्ट नहीं कर सकता? – Andremoniy

+4

क्योंकि 'ऑब्जेक्ट', जेएलएस उद्धरण में 'टी' के रूप में दर्शाया गया है, एक कार्यात्मक इंटरफ़ेस प्रकार नहीं है। –

3

मुझे लगता है यह एक विशुद्ध रूप से विश्वविद्यालय के सवाल यह है कि, के बाद से मैं किसी भी असली नहीं देख सकते हैं इसके लिए जीवन का उपयोग मामला। फिर भी, मुझे पूरा यकीन है कि इसे Stream::of लैम्ब्डा अभिव्यक्ति के साथ करना है। तुम भी ऐसा नहीं कर सकता है:

Object of_ref = list -> Stream.of(list); 

मैं अनुमान है कि एक सटीक वापसी प्रकार संकलक जो FunctionalInterface यह प्रयोग किया जा रहा बताता है। इस जानकारी के बिना संकलक के लिए लैम्ब्डा अभिव्यक्ति को सही ढंग से और स्पष्ट रूप से हल करना असंभव है।

4

मुख्य बिंदु यह है कि जावा में कोई "फ़ंक्शन प्रकार" नहीं है। एक लैम्ब्डा अभिव्यक्ति में स्वयं "प्रकार" नहीं होता है - इसे पर कार्यात्मक इंटरफ़ेस टाइप किया जा सकता है जिसका एकमात्र तरीका हस्ताक्षर लैम्ब्डा से मेल खाता है। इसलिए, एक लैम्ब्डा का प्रकार इसके संदर्भ द्वारा प्रदान किए गए प्रकार पर आधारित होता है। एक प्रकार के लिए संदर्भ के रूप में आपको एक कार्यात्मक इंटरफ़ेस प्रदान करना होगा।

यह एक ही मुद्दे पर विचार करने के लिए निर्देशक है लेकिन अज्ञात वर्गों के लिए। यद्यपि लैम्बडास और अज्ञात वर्गों के बीच कार्यान्वयन अंतर हैं, अर्थात्, लैम्ब्डा अनिवार्य रूप से अज्ञात वर्गों के उप-समूह के बराबर हैं, और लैम्ब्डा अभिव्यक्ति को हमेशा समकक्ष अज्ञात वर्ग निर्माण अभिव्यक्ति में परिवर्तित किया जा सकता है।

जब आप लिखें:

Function<T, Stream<T>> of_ref = Stream::of; 

यह निम्नलिखित गुमनाम वर्गों का उपयोग की तरह कुछ के बराबर है:

Function<T, Stream<T>> of_ref = new Function<T, Stream<T>>() { 
    Stream<T> apply(T t) { 
     return Stream.of(t); 
    } 
}; 

अब विचार करना

Object of_ref = Stream::of; 

गुमनाम वर्गों के साथ बराबर है क्या ?

Object of_ref = new [**What goes here?**]() { 
    [**What method signature goes here?**] { 
     return Stream.of(t); 
    } 
}; 

आप देखते हैं कि यह क्यों समझ में नहीं आता है - हम नहीं जानते कि अनाम वर्ग के बेस क्लास के रूप में किस प्रकार का उपयोग करना है।

+0

ठीक है! इसका मतलब है कि यह सिर्फ वाक्य रचनात्मक चीनी है, हाँ? – Andremoniy

+0

@Andremoniy: ठीक है, यह इस बात पर निर्भर करता है कि आप "वाक्य रचनात्मक चीनी" को कैसे परिभाषित करते हैं। कुछ मामलों में कुछ रूपांतरण जरूरी है (उदाहरण के लिए लैम्बडा में 'यह' 'OuterClass.this' के बराबर है, न कि अज्ञात वर्ग में 'यह'), और कुछ व्यवहारिक मतभेद हैं, जैसे कि दो अज्ञात वर्ग वस्तुएं अलग हैं (' ! = '), लेकिन दो भेड़ का बच्चा नहीं हो सकता है। लेकिन अधिकांश भाग के लिए आप इसे एक वाक्य रचनात्मक चीनी के रूप में सोच सकते हैं। – newacct

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

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