2013-02-09 12 views
8

मैं बंद समझता हूं और कुछ भाषा जैसे पायथन और एसएमएल में लागू होता हूं। फिर भी, जब मैं जावा में बंद होने के बारे में विकिपीडिया पढ़ता हूं (बेशक, केवल 8 संस्करण), यदि जावा बंद होने का समर्थन करता है या नहीं तो मुझे अंतर नहीं लगता है।जावा: इस कोड में क्लोजर को समझाएं

उन कोड विकिपीडिया से मैं कॉपी: Closure

बंद के बिना जावा कोड:

class CalculationWindow extends JFrame { 
    private volatile int result; 
    ... 
    public void calculateInSeparateThread(final URI uri) { 
    // The expression "new Runnable() { ... }" is an anonymous class implementing the 'Runnable' interface. 
    new Thread(
     new Runnable() { 
     void run() { 
      // It can read final local variables: 
      calculate(uri); 
      // It can access private fields of the enclosing class: 
      result = result + 10; 
     } 
     } 
    ).start(); 
    } 
} 

और अगर जावा बंद का समर्थन करता है, कोड इच्छा की तरह दिखता है:

class CalculationWindow extends JFrame { 
private volatile int result; 
    ... 
    public void calculateInSeparateThread(final URI uri) { 
    // the code() -> { /* code */ } is a closure 
    new Thread(() -> { 
     calculate(uri); 
     result = result + 10; 
    }).start(); 
    } 
} 

तो, मेरा सवाल है: यदि जावा बंद करने का समर्थन करता है, तो दूसरी कोड में कौन सी विशेष बात है? मैं वास्तव में दो कोड के बीच मुख्य अंतर नहीं देखता हूं।

कृपया मुझे यह बिंदु बताएं।

धन्यवाद :)

उत्तर

2

अंतर यह है कि है:

    पहला मामला आप एक अनाम वर्ग की घोषणा कर रहे हैं और एक उदाहरण बनाने में
  • , लेकिन
  • दूसरे मामले में
  • कोई वर्ग है और कोई उदाहरण नहीं इसके बजाए, एक लैम्ब्डा है ... प्रभावी ढंग से एक अनाम समारोह।

वे एक ही अंत को प्राप्त है, लेकिन लैम्ब्डा वाक्यविन्यास निश्चित रूप से अधिक हल्के वजन है।

हालांकि, एक लैम्ब्डा केवल उस क्षेत्र में स्थानीय चरों तक पहुंच सकता है जिसमें यह घोषित किया जाता है कि वे final (या प्रभावी रूप से अंतिम) हैं; जेएसआर-000335 समीक्षा ड्राफ्ट # 2 में 15.27.2 देखें। तो आप तर्क दे सकते हैं कि जावा लैम्बदास पूर्ण बंद नहीं हैं।

लेकिन जेएसआर-000335 spec का अर्थ यह है कि लैम्बडा अज्ञात वर्ग नहीं हैं। और this और super लैम्ब्डा शरीर में एक अलग अर्थ है कि वे एक विधि में करते हैं।

spec lambdas (एक बिंदु पर) को "सिंथेटिक कक्षाओं" का उपयोग करके कार्यान्वित करने के रूप में वर्णित करता है, और यह बताता है कि संकलन अनुकूलन के रूप में उचित होने पर सिंथेटिक कक्षाओं का एक उदाहरण पुन: उपयोग किया जा सकता है। (इसके विपरीत, संकलक को अज्ञात वर्ग के लिए अनुकूलन करने की अनुमति नहीं दी जाएगी।) इस अनुकूलन का अर्थ है कि लैम्बडा अज्ञात वर्गों का उपयोग करके समकक्ष कोडित से बेहतर प्रदर्शन करने के लिए हैं।

() -> { 
    calculate(uri); 
    result = result + 10; 
} 

रन() विधि के किसी समान कार्यान्वयन के साथ Runnable का एक नया वर्ग उदाहरण के बराबर है:

+1

यह अभी भी एक अज्ञात वर्ग का एक उदाहरण है। और नहीं, यह अधिक शक्तिशाली नहीं है। – newacct

4

मुद्दा यह है कि वे वास्तव में बहुत अलग कार्यात्मक नहीं हैं। आप बहुत सारे "बॉयलर-प्लेट" कोड को एक साधारण लैम्ब्डा फ़ंक्शन के साथ प्रतिस्थापित करते हैं।

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

0

ठीक है, मुख्य रूप से दो अंतर हैं। पहला वाला जावैक और जेवीएम में होने वाली अंतर्निहित प्रक्रिया से जुड़ा हुआ है, और दूसरा सिंटैक्स है।

स्पष्टीकरण देने से पहले, 'असली' कार्यात्मक भाषा में बंद होने से बहुत जल्दी परिभाषित किया जाता है: एक कार्य अपने व्याख्यात्मक वातावरण और स्मृति संदर्भ के साथ आ रहा है।

पहले, संकलक इस कोड को 'सिंटेक्सीक संदर्भ' स्कैनिंग द्वारा हल करेगा जिसमें कोड निष्पादित किया जा रहा है (वेरिएबल्स नहीं, लेकिन आपके द्वारा लिखे गए कोड को संकलक स्थिर जांच करता है)। यदि यह पाया जाता है कि आप एक विधि के पैरामीटर के रूप में एक लैम्ब्डा लिख ​​रहे हैं जो एक कार्यात्मक इंटरफ़ेस की प्रतीक्षा कर रहा है, तो आप संकलित करने में सक्षम होंगे ताकि JVM निष्पादित करने के लिए कोड की सही शांति पा सके। वास्तव में आप एक इंटरफेस को लागू करने जा रहे हैं जो फ्लाई पर केवल एक हस्ताक्षर का खुलासा करता है।

फिर, स्वयं द्वारा सिंटैक्स महत्वपूर्ण है क्योंकि यह आपको अज्ञात वर्ग की तुलना में एक ही शक्ति नहीं देगा जहां आप एक ही स्थान पर कई विधियों को लागू या ओवरराइड कर पाएंगे।

प्रश्न में कोड का टुकड़ा दो अवधारणाओं के बीच अंतर देखने के लिए बहुत प्रासंगिक नहीं है और यह पूरी तरह से 'बंद' का उपयोग नहीं कर रहा है।

public class MyClass 
{ 
    // A one method interface. 
    public static interface Function 
    { 
     void execute(int a); 
    }; 

    // An implementation of Function using the closure and lambda. 
    public static Function createPrintAddToTenFunction() 
    { 
     Integer x = 10; 
     Function func = (a) -> System.out.println(x + a); 
     return func; 
    } 

    // A basic program. 
    public static void main(String args[]) 
    { 
     Function func = createPrintAddToTenFunction(); 
     func.execute(10); 
    } 
} 

यह जावा 8 में संकलन और प्रिंट होगा: 20

लेकिन, बंद के साथ जावा में कुछ अजीब है यहाँ कोड का एक टुकड़ा मदद कर सकता है ते संभावित देखते हैं। इस कोड में online documentation, लिस्टिंग 14 से आ रही है:

public static void main(String... args) { 
    StringBuilder message = new StringBuilder(); 
    Runnable r =() -> System.out.println(message); 
    message.append("Howdy, "); 
    message.append("world!"); 
    r.run(); 
} 

यह Howdy, world!

प्रिंट होगा और वह है सिर्फ तुम क्या एक कार्यात्मक प्रोग्रामिंग भाषा में नहीं करना चाहती। JVM ऐसा कारण है जावा जावा ऑब्जेक्ट उन्मुख भाषा है और इसमें बहुत अच्छा है।

जावा में आप ढेर के बहुत सारे संदर्भों का उपयोग करते हैं (जो सी या किसी भी नज़दीक सी ++ जैसी भाषा में पॉइंटर्स के करीब हैं)। इस सिद्धांत के साथ, यदि आप निष्पादन स्टैक में इसका संदर्भ एम्बेड करते हैं, तो आप प्रोग्राम के मेमोरी संदर्भ में शुरू किए गए चर को संशोधित करने में सक्षम हैं। यह Von Neumann Architecture से आने वाला अंतर्निहित सिद्धांत है। यह एक कार्यात्मक भाषा से अलग है जो अलग-अलग निष्पादन संदर्भों को एक दूसरे में संलग्न करना चाहिए जो कि अलग-अलग है और यह सुनिश्चित करेगा कि एक चर द्वारा संदर्भित मान को चर के बाद के असाइनमेंट द्वारा संशोधित नहीं किया जाएगा। लेकिन यह एक और कहानी है।

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