2016-10-25 8 views
5

इस कोड के बीच क्या अंतर है?जब हमें जावा 8 में प्रदायक का उपयोग करना चाहिए?

Supplier<LocalDate> s1 = LocalDate::now; 
LocalDate s2 = LocalDate.now(); 

System.out.println(s1.get()); //2016-10-25 
System.out.println(s2); //2016-10-25 

मैं जावा 8 में कार्यात्मक इंटरफेस सीखना शुरू करता हूं और यह नहीं समझता कि कौन सा लाभ प्रदायक प्रदान करता है। कब और कैसे, बिल्कुल, हमें उसका उपयोग करना चाहिए। क्या प्रदायक प्रदर्शन को बेहतर बनाता है या शायद अमूर्त स्तर पर लाभ?

आपके उत्तरों के लिए धन्यवाद! और यह डुप्लिकेट प्रश्न नहीं है क्योंकि मैंने खोज का उपयोग किया था और मुझे जो चाहिए वह नहीं मिला।

अद्यतन 1: आपका मतलब यह है?

Supplier<Long> s1 = System::currentTimeMillis; 
    Long s2 = System.currentTimeMillis(); 

    System.out.println(s1.get()); //1477411877817 
    System.out.println(s2); //1477411877817 
    try { 
     Thread.sleep(3000l); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    System.out.println(s1.get()); //1477411880817 - different 
    System.out.println(s2); //1477411877817 
+2

's2':

John Doe is 5 John Doe is 6 

हमारी इकाई परीक्षण" अब "इस तरह की तारीख इंजेक्षन कर सकते हैं उस बिंदु पर आपको "अब" देगा जहां 's2' असाइन किया गया था। 's1.get() 'आपको उस बिंदु पर" अब "देगा जब आप' get()' को कॉल करते हैं। यह तब भी नहीं हो सकता है जब आप आवश्यक होने पर कहीं भी 'प्रदायक' का उपयोग कर चुके हों। फिर यदि आप बाद में 's1.get()' को कॉल करते हैं, तो आपको फिर से एक अलग समय मिल जाएगा। – khelwood

+0

@ शेल्ववुड, मुझे यह नहीं मिला और प्रश्न अपडेट किया गया, कृपया जांचें। – badCoder

+1

इसका उपयोग तब करें जब आपको _multiple values_ को _another method_ में प्राप्त करने की क्षमता पारित करने की आवश्यकता हो ._ यह वैध उपयोग मामलों में से 100% है। –

उत्तर

2

यह निश्चित रूप से प्रदर्शन में सुधार नहीं करता है। आपका प्रश्न इस जैसा है: हम चर का उपयोग क्यों कर रहे हैं? हर बार जब हमें इसकी ज़रूरत होती है तो हम बस सबकुछ फिर से समझ सकते हैं। सही?

यदि आपको कई बार विधि का उपयोग करने की आवश्यकता है, लेकिन इसमें एक शब्दकोष वाक्यविन्यास है।

मान लेते हैं तो आप एक वर्ग MyAmazingClass नामित है, और आप नाम MyEvenBetterMethod (जो स्थिर होता है) के साथ उस में एक विधि है, और आप इसे अपने कोड में 15 अलग अलग स्थानों पर 15 बार कॉल करने की आवश्यकता हैं। बेशक, आप कुछ की तरह कर सकते हैं ...

int myVar = MyAmazingClass.MyEvenBetterMethod(); 
// ... 
int myOtherVar = MyAmazingClass.MyEvenBetterMethod(); 
// And so on... 

... लेकिन आप भी

Supplier<MyAmazingClass> shorter = MyAmazingClass::MyEvenBetterMethod; 

int myVar = shorter.get(); 
// ... 
int myOtherVar = shorter.get(); 
// And so on... 
+4

निश्चित रूप से वह 'प्रदायक ' होगा। और इसे प्रदर्शन के साथ कुछ भी नहीं मिला है या एक विधि कितनी शब्दावली है। एक अर्थपूर्ण अंतर है। – biziclop

7

आप कार्यात्मक इंटरफेस और विधि संदर्भ भ्रमित कर रहे हैं कर सकते हैं। Supplier सिर्फ Callable जैसा है, जिसे आपको जावा 5 के बाद पता होना चाहिए, केवल Callable.call को एस को फेंकने की अनुमति है, Supplier.get के विपरीत। तो इन इंटरफेस में समान उपयोग के मामले होंगे।

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

तो जावा 8 से पहले, आप

Future<Double> f=executorService.submit(new Callable<Double>() { 
    public Double call() throws Exception { 
     return calculatePI(); 
    } 
}); 
/* do some other work */ 
Double result=f.get(); 

लिखना पड़ा और अब, आप

Future<Double> f=executorService.submit(() -> calculatePI()); 
/* do some other work */ 
Double result=f.get(); 

या

Future<Double> f=executorService.submit(MyClass::calculatePI); 
/* do some other work */ 
Double result=f.get(); 

सवाल बारे में जबCallable hasn उपयोग करने के लिए कर सकते हैं बिल्कुल नहीं बदला।

इसी तरह, प्रश्न जब Supplier उपयोग करने के लिए आप इसे कैसे लागू पर निर्भर नहीं है, लेकिन जो एपीआई का उपयोग करें, यानी

CompletableFuture<Double> f=CompletableFuture.supplyAsync(MyClass::calculatePI); 
/* do some other work */ 
Double result=f.join();// unlike Future.get, no checked exception to handle... 
1

मैं एक परिदृश्य में जहाँ हम Supplier<LocalDate> बजाय LocalDate का उपयोग करना चाहिए के माध्यम से जाना होगा ।

कोड कि सीधे LocalDate.now() की तरह स्थिर तरीकों को कॉल करता है इकाई परीक्षण करने के लिए बहुत मुश्किल है।

class Person { 
    final String name; 
    private final LocalDate dateOfBirth; 

    Person(String name, LocalDate dateOfBirth) { 
     this.name = name; 
     this.dateOfBirth = dateOfBirth; 
    } 

    long getAge() { 
     return ChronoUnit.YEARS.between(dateOfBirth, LocalDate.now()); 
    } 
} 

यह उत्पादन में ठीक काम करता है: एक विधि getAge() कि एक व्यक्ति की आयु की गणना करता है परीक्षण एक परिदृश्य में जहाँ हम इकाई के लिए चाहते हैं पर विचार करें। लेकिन एक यूनिट टेस्ट को या तो सिस्टम की तारीख को किसी ज्ञात मूल्य पर सेट करना होगा या हर साल अपडेट किया जाना चाहिए ताकि वापसी की उम्र एक के द्वारा बढ़ाया जा सके, दोनों बहुत ही भयानक समाधान।

एक बेहतर समाधान इकाई परीक्षण एक ज्ञात तारीख में इंजेक्ट करने के लिए, जबकि अभी भी उत्पादन कोड LocalDate.now() उपयोग करने की अनुमति होगी। शायद इस तरह कुछ:

class Person { 
    final String name; 
    private final LocalDate dateOfBirth; 
    private final LocalDate currentDate; 

    // Used by regular production code 
    Person(String name, LocalDate dateOfBirth) { 
     this(name, dateOfBirth, LocalDate.now()); 
    } 

    // Visible for test 
    Person(String name, LocalDate dateOfBirth, LocalDate currentDate) { 
     this.name = name; 
     this.dateOfBirth = dateOfBirth; 
     this.currentDate = currentDate; 
    } 

    long getAge() { 
     return ChronoUnit.YEARS.between(dateOfBirth, currentDate); 
    } 

} 

उस परिदृश्य पर विचार करें जहां ऑब्जेक्ट बनाया गया था, व्यक्ति का जन्मदिन बीत चुका है। इस कार्यान्वयन के साथ, getAge() उस समय पर आधारित होगा जब व्यक्ति ऑब्जेक्ट को वर्तमान दिनांक की बजाय बनाया गया था। हम Supplier<LocalDate> का उपयोग करके इस का समाधान कर सकते हैं:

class Person { 
    final String name; 
    private final LocalDate dateOfBirth; 
    private final Supplier<LocalDate> currentDate; 

    // Used by regular production code 
    Person(String name, LocalDate dateOfBirth) { 
     this(name, dateOfBirth,()-> LocalDate.now()); 
    } 

    // Visible for test 
    Person(String name, LocalDate dateOfBirth, Supplier<LocalDate> currentDate) { 
     this.name = name; 
     this.dateOfBirth = dateOfBirth; 
     this.currentDate = currentDate; 
    } 

    long getAge() { 
     return ChronoUnit.YEARS.between(dateOfBirth, currentDate.get()); 
    } 

    public static void main(String... args) throws InterruptedException { 
     // current date 2016-02-11 
     Person person = new Person("John Doe", LocalDate.parse("2010-02-12")); 
     printAge(person); 
     TimeUnit.DAYS.sleep(1); 
     printAge(person); 
    } 

    private static void printAge(Person person) { 
     System.out.println(person.name + " is " + person.getAge()); 
    } 
} 

उत्पादन सही ढंग से होगा:

@Test 
void testGetAge() { 
    Supplier<LocalDate> injectedNow =()-> LocalDate.parse("2016-12-01"); 
    Person person = new Person("John Doe", LocalDate.parse("2004-12-01"), injectedNow); 
    assertEquals(12, person.getAge()); 
} 
संबंधित मुद्दे