2016-03-10 8 views
5

के बीच अंतर मैं अपने कोड में जावा 8 विधि संदर्भों का उपयोग करने की कोशिश कर रहा हूं। चार प्रकार के विधि संदर्भ उपलब्ध हैं।जावा 8: विधि संदर्भ बाउंड रिसीवर और अनबाउंड रिसीवर

  1. स्टेटिक विधि संदर्भ।
  2. इंस्टेंस विधि (बाउंड रिसीवर)।
  3. इंस्टेंस विधि (अनबाउंड रिसीवर)।
  4. कन्स्ट्रक्टर संदर्भ।

Static method reference और Constructor reference मैं कोई समस्या नहीं है, लेकिन Instance Method (Bound receiver) और Instance Method (UnBound receiver) के साथ वास्तव में मुझे उलझन में।

objectRef::Instance Method 

UnBound में रिसीवर हम की तरह एक विधि फोन करने के लिए कक्षा का नाम प्रयोग कर रहे हैं: Bound रिसीवर में, हम की तरह एक विधि फोन करने के लिए एक वस्तु संदर्भ चर का उपयोग कर रहे

ClassName::Instance Method. 

मैं निम्नलिखित प्रश्न है :

  1. इंस्टेंस विधियों के लिए विभिन्न प्रकार के विधि संदर्भों की आवश्यकता क्या है?
  2. Bound और Unbound रिसीवर विधि संदर्भों के बीच क्या अंतर है?
  3. हमें Bound रिसीवर का उपयोग कहां करना चाहिए और हमें Unbound रिसीवर का उपयोग कहां करना चाहिए?

मैं भी Java 8 language features books से Bound और Unbound रिसीवर के स्पष्टीकरण मिल गया, लेकिन अभी भी वास्तविक अवधारणा के साथ भ्रमित किया गया था।

उत्तर

7

अनबाउंड रिसीवर String::length रूप में इस तरह के विचार है कि आप एक उद्देश्य यह है कि लैम्ब्डा के मापदंडों में से एक के रूप में आपूर्ति की जाएगी करने के लिए एक विधि संदर्भ दे रहे है। उदाहरण के लिए, लैम्ब्डा अभिव्यक्ति (String s) -> s.toUpperCase() को String::toUpperCase के रूप में पुनः लिखा जा सकता है।

लेकिन जब आप एक बाहरी वस्तु पहले से मौजूद है करने के लिए एक लैम्ब्डा में एक विधि कॉल कर रहे हैं घिरा एक स्थिति को दर्शाता है। उदाहरण के लिए, लैम्ब्डा अभिव्यक्ति () -> expensiveTransaction.getValue() को expensiveTransaction::getValue के रूप में पुनः लिखा जा सकता है। विधि संदर्भ के तीन अलग अलग तरीकों के लिए

हालात

(args) -> ClassName.staticMethod(args) हो सकता है ClassName::staticMethod

(arg0, rest) -> arg0.instanceMethod(rest) हो सकता है ClassName::instanceMethod

(args) -> expr.instanceMethod(args) हो सकता है (arg0 प्रकार ClassName की है) expr::instanceMethod

एक्शन बुक

6

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

एक उदाहरण इस स्पष्ट कर सकता है:

import java.util.function.*; 

public class Test { 

    private final String name; 

    public Test(String name) { 
     this.name = name; 
    } 

    public static void main(String[] args) { 
     Test t1 = new Test("t1"); 
     Test t2 = new Test("t2"); 

     Supplier<String> supplier = t2::method; 
     Function<Test, String> function = Test::method; 

     // No need to say which instance to call it on - 
     // the supplier is bound to t2    
     System.out.println(supplier.get()); 

     // The function is unbound, so you need to specify 
     // which instance to call it on 
     System.out.println(function.apply(t1)); 
     System.out.println(function.apply(t2)); 
    } 

    public String method() { 
     return name; 
    } 
} 
+0

एक छोटी क्वेरी में जावा 8 से सेवानिवृत्त उत्तर। आपने लिखा है: प्रदायक आपूर्तिकर्ता = टी 2 :: विधि; और टिप्पणी के रूप में प्रदान की: // आपूर्तिकर्ता टी 1 के लिए बाध्य है। क्या यह टाइपो त्रुटि है या क्या मैं ठीक से समझ नहीं रहा हूं? –

+1

@Ravindrababu: बस एक टाइपो। अभी ठीक कर रहा है ... –

2

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

उदाहरण के लिए:

Stream.of("x","y").forEach(System.out::println); 

PrintStream के sepcific उदाहरण पर println निष्पादित करेंगे - System.out उदाहरण। इसलिए System.out.println("x") और System.out.println("y") को forEach पर उस विधि संदर्भ को पारित करने के परिणामस्वरूप निष्पादित किया जाएगा।

दूसरी तरफ, यदि आप कक्षा के अनिर्दिष्ट उदाहरण के लिए विधि को निष्पादित करना चाहते हैं, तो आप एक अनबाउंड रिसीवर का उपयोग कर सकते हैं।

उदाहरण के लिए:

Stream.of("x","y","").filter(String::isEmpty); 

स्ट्रीम के String उदाहरणों में से प्रत्येक पर isEmpty() निष्पादित करेंगे - यानी "x".isEmpty(), "y".isEmpty() और "".isEmpty()

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