2017-04-20 14 views
45

मैं क्यों निम्नलिखित कोड को संकलित करता है देखने के लिए संघर्ष कर रहा हूँ:इस विधि संदर्भ असाइनमेंट संकलन क्यों करता है?

public class MethodRefs { 

    public static void main(String[] args) { 
     Function<MethodRefs, String> f; 

     f = MethodRefs::getValueStatic; 

     f = MethodRefs::getValue; 
    } 

    public static String getValueStatic(MethodRefs smt) { 
     return smt.getValue(); 
    } 

    public String getValue() { 
     return "4"; 
    } 

} 

मैं देख सकता हूँ क्यों पहला काम वैध है - getValueStatic स्पष्ट रूप से निर्दिष्ट Function प्रकार (यह एक MethodRefs वस्तु स्वीकार करता है और देता है एक String) से मेल खाता है, लेकिन दूसरा मुझे परेशान करता है - getValue विधि कोई तर्क स्वीकार नहीं करता है, तो यह अभी भी f पर असाइन करने के लिए मान्य क्यों है?

+1

जावा 8 में गैर-स्थैतिक तरीकों के साथ [लैम्ब्डा का संभावित डुप्लिकेट] (http://stackoverflow.com/questions/25784337/lambda-with-non-static-methods-in-java-8) –

+1

इसके अलावा [: : जावा में डबल (डबल कॉलन) ऑपरेटर 8] (http://stackoverflow.com/questions/20001427/double-colon-operator-in-java-8/22245383#22245383) और [डबल कॉलन का उपयोग - स्थिर और अंतर के बीच अंतर गैर स्थैतिक विधि संदर्भ] (http://stackoverflow.com/questions/34982972/use-of-double-colons-difference-between-static-and-non-static-method-reference?noredirect=1&lq=1) –

उत्तर

50

दूसरा एक

f = MethodRefs::getValue; 

वहाँ हमेशा एक अंतर्निहित तर्क जो कॉल प्राप्त करने वाला में this के रूप में प्रतिनिधित्व कर रहा है

f = (MethodRefs m) -> m.getValue(); 

रूप में एक ही गैर स्थिर विधियों के लिए है।

नोट: कार्यान्वयन बाइट कोड स्तर पर थोड़ा अलग है लेकिन यह वही काम करता है।

+24

ध्यान दें कि निहित तर्क स्पष्ट किया जा सकता है (जावा 8 के रूप में): 'पब्लिक स्ट्रिंग getValue (MethodRefs this) 'कानूनी है और' सार्वजनिक स्ट्रिंग getValue()' के समान है। – Pokechu22

+0

@ Pokechu22 मुझे यह नहीं पता था।क्या उस निर्माण के लिए कोई नाम है? – immibis

+5

@immibis: [spec] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1) (§8.4.1) इसे कॉल करता है जहां तक ​​मैं कह सकता हूं "रिसीवर पैरामीटर"। – Pokechu22

5

गैर स्थैतिक तरीकों के लिए, this का प्रकार पहले तर्क प्रकार के रूप में माना जाता है। चूंकि यह MethodRefs प्रकार है, प्रकारों की जांच करें।

9

एक गैर स्थैतिक विधि अनिवार्य रूप से this संदर्भ को विशेष प्रकार के तर्क के रूप में संदर्भित करती है। आम तौर पर तर्क एक विशेष तरीके से लिखा जाता है (विधि नाम से पहले, इसके बाद कोष्ठक के अंदर), लेकिन अवधारणा वही है। getValue विधि MethodRefs ऑब्जेक्ट (इसकी this) लेती है और एक स्ट्रिंग देता है, इसलिए यह Function<MethodRefs, String> इंटरफ़ेस के साथ संगत है।

9

यह शरीर से बाहर एक सा देता है:

import java.util.function.Function; 

public class MethodRefs { 

    public static void main(String[] args) { 
    Function<MethodRefs, String> f; 


    final MethodRefs ref = new MethodRefs(); 

    f = MethodRefs::getValueStatic; 
    f.apply(ref); 
    //is equivalent to 
    MethodRefs.getValueStatic(ref); 

    f = MethodRefs::getValue; 
    f.apply(ref); 
    //is now equivalent to 
    ref.getValue(); 
    } 

    public static String getValueStatic(MethodRefs smt) { 
    return smt.getValue(); 
    } 

    public String getValue() { 
    return "4"; 
    } 
} 
6

जावा ट्यूटोरियल में यह स्पष्ट किया गया है वहाँ विधि संदर्भ के 4 विभिन्न प्रकार के होते हैं: एक स्थिर विधि

  • संदर्भ के लिए

    1. संदर्भ किसी विशेष ऑब्जेक्ट की एक उदाहरण विधि
    2. reference to an instance method of an arbitrary object of a particular type
    3. r एक निर्माता

    आपका मामला को eference # 3, जिसका अर्थ है कि आप MethodRef अर्थात ref का एक उदाहरण है जब, अपने कार्य पर apply बुला fString s = ref.getValue() के बराबर हो जाएगा।

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