2017-05-01 20 views
5

नीचे दी गई कक्षा में, मैं विधि संदर्भ WordCounterEx::accumulate को कम करने के तरीके के दूसरे पैरामीटर के रूप में पास करता हूं। विधि को कम के हस्ताक्षर है:विधि संदर्भ कार्यात्मक इंटरफ़ेस अनुबंध को पूरा नहीं करता है लेकिन यह संकलित करता है। यह कैसे संभव है?

<U> U reduce(U identity, 
      BiFunction<U, ? super T, U> accumulator, 
      BinaryOperator<U> combiner); 

इस प्रकार विधि को कम करने, BiFunction नुस्खा पूरा करना चाहिए के दूसरे पैरामीटर। लेकिन पारित संचय विधि बीआईएफक्शन नहीं है (इसमें केवल एक पैरामीटर है)। यह अभी भी संकलित क्यों है?

public class WordCounterEx { 
    private final int counter; 
    private final boolean lastSpace; 

    public WordCounterEx(int counter, boolean lastSpace) { 
     this.counter = counter; 
     this.lastSpace = lastSpace; 
    } 

    public int countWords(Stream<Character> stream) { 
     WordCounterEx wordCounter = stream.reduce(new WordCounterEx(0, true), 
       //HOW CAN THIS WORK? here must come BiFunction - R apply(T t, U u); 
       WordCounterEx::accumulate, 
       WordCounterEx::combine); 
     return wordCounter.counter; 
    } 

    public WordCounterEx accumulate(Character c) { 
     if(Character.isWhitespace(c)) { 
      return lastSpace ? 
        this : 
        new WordCounterEx(counter, true); 
     } else { 
      return lastSpace ? 
        new WordCounterEx(counter+1, false) : 
        this; 
     } 
    } 

    public WordCounterEx combine(WordCounterEx wordCounter) { 
     return new WordCounterEx(counter + wordCounter.counter 
       ,wordCounter.lastSpace /*does not matter*/); 
    } 
} 

उत्तर

3

accumulate() एक उदाहरण विधि है, और आप (नहीं उदाहरण और विधि नाम से) वर्ग के नाम और विधि नाम से कहते हैं। तो अगर मैं उस विधि को कॉल करना चाहता हूं जो आप मुझे दे रहे हैं, तो मैं आमतौर पर myEx.accumulate(myCh) करता हूं। इस प्रकार मैं दो चीजें प्रदान करता हूं, WordCounterEx उदाहरण और चरित्र। इसलिए, इस विधि का उपयोग BiFunction<WordCounterEx, ? super Character, WordCounterEx> के रूप में किया जाता है।

इसके बजाय यदि आपने मुझे उदाहरण this::accumulate के लिए दिया था, वस्तु होता दिया गया है पर विधि (this) कॉल करने के लिए, और यह अब मैं "विधि को कम मेरी ग्रहण में (एक BiFunction रूप में इस्तेमाल किया जा सकता है (यू, बायफंक्शन, बाइनरीऑपरेटर) प्रकार स्ट्रीम में तर्कों के लिए लागू नहीं है (वर्डकॉन्टरएक्स, यह :: संचित, वर्डकॉन्टरएक्स :: गठबंधन) ")।

+2

नोट जावा 8 में आप एक तर्क के रूप 'गुजारें सकता है कि this', जो हस्ताक्षर से पूरी तरह मेल खाता है: 'सार्वजनिक वर्डकॉन्टरएक्स जमा (वर्डकॉन्टरएक्स यह, कैरेक्टर सी) '। यह प्रश्न में जैसे तर्क के रूप में 'this' के बिना संस्करण के बराबर है। –

1

WordCounterEx#countWords विधि इस प्रकार है फिर से लिखा जा सकता है:

public int countWordsWithInstance(Stream<Character> stream) { 
    WordCounterEx wordCounter = stream.reduce(new WordCounterEx(0, true), 
      this::accumulate, 
      WordCounterEx::combine); 
    return wordCounter.counter; 
} 

public WordCounterEx accumulate(WordCounterEx wc,Character c) { 
    if(Character.isWhitespace(c)) { 
     return wc.lastSpace ? 
       wc : 
       new WordCounterEx(wc.counter, true); 
    } else { 
     return wc.lastSpace ? 
       new WordCounterEx(wc.counter+1, false) : 
       wc; 
    } 
} 

इस मामले में जमा विधि होनी चाहिए WordCounterEx wc अपने हस्ताक्षर में

+2

यह सच है। इसके एक रूप के रूप में आप 'जमा() 'स्थिर' घोषित कर सकते हैं और इसे 'वर्डकॉन्टरएक्स :: जमा करें' (जैसा कि आप जानते हैं) के रूप में संदर्भित करते हैं (यह काम करता है क्योंकि, जैसा कि आप जानते हैं, 'स्थैतिक' विधियों को बिना बुलाया जाता है एक वस्तु)। –

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