2017-02-01 4 views
5

इस उदाहरण पर विचार करें:लैम्बडा से कौन सा कार्यात्मक इंटरफ़ेस बनाने का निर्णय लेता है?

import java.util.function.Consumer; 

public class Example { 
    public static void main(String[] args) { 
     Example example = new Example(); 

     example.setConsumer(test -> System.out.println("passed string is " + test)); //uses MyConsumer, why ? 
     example.getConsumer().accept("Test 1"); 

     example.setConsumer((MyConsumer<String>)test -> System.out.println("passed string is " + test)); //uses MyConsumer 
     example.getConsumer().accept("Test 2"); 

     example.setConsumer((Consumer<String>)test -> System.out.println("passed string is " + test)); //uses Consumer 
     example.getConsumer().accept("Test 3"); 
    } 

    private Consumer<String> consumer; 

    public Consumer<String> getConsumer() { 
     return consumer; 
    } 

    public void setConsumer(Consumer<String> consumer) { 
     this.consumer = consumer; 
    } 

    public void setConsumer(MyConsumer<String> consumer) { 
     this.consumer = consumer; 
    } 

    @FunctionalInterface 
    public interface MyConsumer<T> extends Consumer<T> { 
     @Override 
     default void accept(T value) { 
      System.out.println("In consumer string: " + value); //example thing to do 
      receive(value); 
     } 

     void receive(T value); 
    } 
} 

क्या मुझे यहाँ दिलचस्पी पहला परीक्षण है। यह उपभोक्ता के बजाय MyConsumer का उपयोग क्यों कर रहा है? क्या होगा यदि मेरे पास एक ही लैम्ब्डा संरचना के साथ अधिक अलग संभावित उपभोक्ता थे, जिनकी प्राथमिकता है? इसके अलावा, टेस्ट 2 पर जो कलाकार मैं करता हूं उसे मेरे आईडीई द्वारा Redundant के रूप में चिह्नित किया जाता है। इसका मतलब है कि lamdba पहले MyConsumer के रूप में बनाया गया है। ऐसा क्यों ?

मैं जैवैक के साथ इंटेलिजे आइडिया का उपयोग कर रहा हूं।

+0

मुझे नहीं पता कि आप किस आईडीई का उपयोग कर रहे हैं। मुझे लगता है कि यह जेवीएम है, ऑब्जेक्ट के रनटाइम प्रकार का उपयोग करके, जो "निर्णय लेता है"। – duffymo

+3

मुझे लगता है कि जावा सबसे विशिष्ट प्रकार चुनता है, जो इस मामले में 'MyConsumer' है। यदि 'मायकंस्यूमर'' उपभोक्ता 'का उपनिवेश नहीं था, तो मुझे लगता है कि आपको एक त्रुटि मिली होगी कि यह एक महत्वाकांक्षी कॉल है। – marstran

+7

यह सबसे विशिष्ट विधि चुनता है। यदि आपके पास उदाहरण के लिए 'MyConsumer2 उपभोक्ता 'और' सेट कॉन्स्यूमर (MyConsumer2 उपभोक्ता) बढ़ाता है, तो पहला कॉल संदिग्ध होगा और आपके पास संकलन समय त्रुटि होगी। यह भी देखें [जेएलएस 15.12.2.5] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5)। –

उत्तर

6

यह choosing the most specific method की प्रक्रिया के अनुसार के रूप में भाषा विनिर्देश द्वारा परिभाषित किया गया है:

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

...

एक कार्यात्मक इंटरफ़ेस प्रकार एस अधिक विशिष्ट एक अभिव्यक्ति ई के लिए एक कार्यात्मक इंटरफ़ेस प्रकार टी से है अगर टी एस के एक उप-प्रकार और निम्न में से एक सच है (जहां U1 नहीं है। .. यूके और आर 1 पैरामीटर प्रकार और एस, और वी 1 के कैप्चर के फ़ंक्शन प्रकार के प्रकार प्रकार हैं ... वीके और आर 2 पैरामीटर प्रकार और टी के फ़ंक्शन प्रकार के रिटर्न प्रकार हैं):

  • यदि ई स्पष्ट रूप से टाइप की गई लैम्ब्डा अभिव्यक्ति (§15.27.1) है, तो निम्न में से कोई एक सत्य है:
  • आर 2 शून्य है।

  • आर: आर 2।

  • आर 1 और आर 2 कार्यात्मक इंटरफेस प्रकार हैं, और कम से कम एक परिणाम अभिव्यक्ति है, और आर 1 ई के प्रत्येक परिणाम अभिव्यक्ति के लिए आर 2 से अधिक विशिष्ट है।

    (एक ब्लॉक शरीर §15.27.2 में परिभाषित किया गया है के साथ एक लैम्ब्डा अभिव्यक्ति का परिणाम अभिव्यक्ति; एक अभिव्यक्ति शरीर के साथ एक लैम्ब्डा अभिव्यक्ति का परिणाम अभिव्यक्ति बस शरीर में ही है।)

  • R1 एक है आदिम प्रकार, और आर 2 एक संदर्भ प्रकार है, और कम से कम एक परिणाम अभिव्यक्ति है, और ई का प्रत्येक परिणाम अभिव्यक्ति एक आदिम प्रकार का एक स्टैंडअलोन अभिव्यक्ति (§15.2) है।

  • आर 1 एक संदर्भ प्रकार है, और आर 2 एक आदिम प्रकार है, और कम से कम एक परिणाम अभिव्यक्ति है, और ई की प्रत्येक परिणाम अभिव्यक्ति या तो संदर्भ प्रकार या एक बहु अभिव्यक्ति का एक स्टैंडअलोन अभिव्यक्ति है।

  • ई एक सटीक विधि संदर्भ अभिव्यक्ति (§15.13 है।1), तो i) सभी के लिए मैं (1 ≤ मैं ≤ ट), Ui Vi रूप में ही है, और ii) निम्न में से एक सत्य है:
  • आर 2 शून्य है।

  • आर: आर 2।

  • R1, एक आदिम प्रकार है R2 एक संदर्भ प्रकार है, और विधि संदर्भ के लिए संकलन समय घोषणा की वापसी प्रकार है जो एक आदिम प्रकार है।

  • आर 1 एक संदर्भ प्रकार है, आर 2 एक आदिम प्रकार है, और विधि संदर्भ के लिए संकलन-समय की घोषणा में एक रिटर्न प्रकार है जो एक संदर्भ प्रकार है।

  • ई एक parenthesized अभिव्यक्ति है, तो इन शर्तों में से एक निहित अभिव्यक्ति को रिकर्सिवली लागू होता है।

  • यदि ई एक सशर्त अभिव्यक्ति है, तो प्रत्येक दूसरे और तीसरे ऑपरेंड के लिए, इनमें से एक शर्त पुनरावर्ती रूप से लागू होती है।

इसलिए, MyConsumer से Consumer क्योंकि Consumer (T कल्पना में) एक उप प्रकार नहीं है और अधिक विशिष्ट है और दोनों void की वापसी मूल्य की है।

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