2012-12-11 26 views
19

संभव डुप्लिकेट:
Double brace initialisation (anonymous inner class) with diamond operatorगुमनाम आंतरिक कक्षाओं पर हीरा का प्रकार क्यों नहीं हो सकता है?

जावा 7 में और बाद में, हीरा एक मुद्दा बिना सामान्य रूप से तो जैसे पर प्रकार अनुमान लगाने के लिए इस्तेमाल किया जा सकता:

List<String> list = new ArrayList<>(); 

हालांकि, यह अज्ञात आंतरिक कक्षाओं के लिए इस तरह नहीं हो सकता है:

List<String> st = new List<>() { //Doesn't compile 

    //Implementation here 

} 

यह क्यों है? तार्किक रूप से इस परिदृश्य में, मैं निश्चित रूप से String के रूप में प्रकार का अनुमान लगा सकता हूं। क्या इस निर्णय के लिए एक तार्किक कारण है जहां वास्तव में अज्ञात आंतरिक कक्षाओं पर प्रकार का अनुमान नहीं लगाया जा सकता है, या इसे अन्य कारणों से छोड़ा गया था?

+2

@ फिलिप मैं असहमत हूं - वह प्रश्न पूछ रहा है कि क्यों कोड का एक निश्चित टुकड़ा संकलित नहीं करता है (वास्तव में जवाब यह है कि आप अज्ञात आंतरिक कक्षाओं के साथ हीरे का उपयोग नहीं कर सकते हैं), यह तकनीकी/तार्किक कारण पूछ रहा है * क्यों * जावा देव ने उस विशेष प्रतिबंध को जगह में रखना चुना। संबंधित, लेकिन शायद ही कभी एक ही बात है। – berry120

+1

यह जेडीके 9 में काफी सुधार हुआ है: https://bugs.openjdk.java.net/browse/JDK-8062373 –

उत्तर

12

JSR-334 में:

गुमनाम भीतरी वर्गों के साथ हीरे का उपयोग करना समर्थित नहीं है के बाद से सामान्य रूप में ऐसा करने वर्ग फ़ाइल करने के लिए एक्सटेंशन हस्ताक्षर विशेषता की आवश्यकता होती है गैर denotable प्रकार का प्रतिनिधित्व करने के लिए, एक डे वास्तव में JVM परिवर्तन।

मुझे क्या लगता है कि जैसा कि सभी जानते हैं, अज्ञात वर्ग अपनी कक्षा फ़ाइल की एक पीढ़ी की ओर जाता है।

मुझे लगता है कि जेनेरिक प्रकार इन फ़ाइलों के भीतर मौजूद नहीं है और इसके बजाय प्रभावी (स्थैतिक) प्रकार से प्रतिस्थापित किया गया है (इस प्रकार घोषणा प्रकार ऑब्जेक्ट समय पर <String> जैसे स्पष्ट प्रकार द्वारा घोषित किया गया है)।

दरअसल, एक आंतरिक वर्ग से संबंधित फ़ाइल को इसके कई अलग-अलग तत्कालताओं में कभी साझा नहीं किया जाता है, तो इसमें जेनिक्स के साथ परेशान क्यों करें ?! :)।

यह कंपाइलर के लिए एक विस्तार को मजबूर करने के लिए संकलक (जेनिक्स के लिए एक विशेष विशेषता जोड़कर) के लिए अधिक कठिन रूप से प्राप्त करने योग्य (और निश्चित रूप से बेकार) होगा।

1

संक्षेप में, <> कम प्रकार के अनुमानों को कम करता है, यह आपको बिना चेतावनी के बंद कर देता है।

संपादित करें: जैसा कि @ नेटिक्स बताता है कि यह कुछ जांच करता है।

List<Integer> ints = new ArrayList<>(); 
List<String> copy = new ArrayList<>(ints); 

एक संकलन त्रुटि

Error:Error:line (42)error: incompatible types 
required: List<String> 
found: ArrayList<Integer> 

पैदा करता है कि आप देख सकते <> तर्क के प्रकार के ले जा रहा है, copy

+3

बिल्कुल नहीं, हीरा अभी भी एक प्रकार की जांच करता है। यह सरल संग्रह प्रारंभिकरण के लिए स्पष्ट नहीं हो सकता है, लेकिन उदाहरण के लिए एक प्रतिलिपि का उपयोग कर लें: ' कॉपी = नया ऐरेलिस्ट <> (मूल); 'यह सुनिश्चित करता है कि' मूल 'सूची तारों की एक सूची भी है (या अधिक ठीक है 'संग्रह ') बढ़ाता है। – Natix

+0

हालांकि यह सच है, यह इस प्रकार का उपयोग नहीं कर रहा है कि इसका उपयोग कैसे किया जाता है। यह एक तर्क से प्रकार ले रहा है। –

1

दिलचस्प सवालों के प्रकार से प्रकार का निष्कर्ष निकालते नहीं है। समाधान यहां पाया जा सकता है http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9 या यहां Double brace initialisation (anonymous inner class) with diamond operator

कम से कम मैंने कुछ सीखा। प्रश्न के लिए धन्यवाद। ;)

4

गूगल पैदावार, stackoverflow की पोस्ट लंघन, http://mail.openjdk.java.net/pipermail/coin-dev/2011-June/003283.html

के बाद मैं इसे इस तरह है अनुमान लगा रहा हूँ, आम तौर पर एक अनाम वर्ग स्पष्ट प्रकार

interface Foo<N extends Number> 
    { 
     void foo(N n); 
    } 

    Foo<Integer> foo = new Foo<Integer>(){ ... } 

द्वारा कार्यान्वित किया जाता का एक ठोस उपवर्ग है
class AnonFoo_1 implements Foo<Integer>{ ... } 

    Foo<Integer> foo = new AnonFoo_1(); 

मान लीजिए कि हम अनाम कक्षाओं पर हीरा अनुमान की अनुमति देते हैं, तो

01 जैसे जटिल मामले हो सकते हैं
Foo<? extends Runnable> foo = new Foo<>(){ ... } 

अनुमान नियम N=Number&Runnable उत्पन्न करते हैं; पिछली कार्यान्वयन चाल के बाद, हमें

class AnonFoo_2 implements Foo<Number&Runnable>{ ... } 

वर्तमान में इसकी अनुमति नहीं है; सुपर टाइप Foo के प्रकार का प्रकार एक "सामान्य" प्रकार होना चाहिए।


हालांकि, तर्क बहुत मजबूत नहीं है। हम अन्य कार्यान्वयन चाल का आविष्कार यह

class AnonFoo<N extends Number&Runnable> implements Foo<N> 
    { 
     @Override public void foo(N n) 
     { 
      n.intValue(); 
      n.run(); 
     } 
    } 

    Foo<? extends Runnable> foo = new AnonFoo<>(); 

काम संकलक एक ही चाल करने के लिए सक्षम होना चाहिए बनाने के लिए कर सकते हैं।

किसी भी मामले में, कम से कम संकलक को उपयोग के अधिकांश मामलों को अनुमति देना चाहिए जिनमें "अनावश्यक प्रकार" शामिल नहीं हैं, जैसे Foo<Integer> foo = new Foo<>(){...} यह दयालु है कि इन आम/साधारण मामलों को भी अनावश्यक रूप से प्रतिबंधित किया जाता है।

+0

आपका उदाहरण सख्ती से एक साधारण (गैर-अज्ञात) ठोस वर्ग के साथ लागू होता है। आपके नमूने में अज्ञात वर्ग से संबंधित विशिष्ट सुविधा क्या है? दरअसल, यदि आपका सिद्धांत सत्य था, तो क्या मामला कभी भी लागू नहीं हो सकता है। – Mik378

+0

बाइटकोड स्तर पर, मुझे नहीं लगता कि अनाम कक्षाओं के बारे में कुछ खास है। – irreputable

+0

तो अपने नमूना ठीक उसी तरीके से करने के बजाय अगर एक अंतरफलक 'होने कैसा व्यवहार करेंगे Foo' आपके पास: वर्ग फू <एन संख्या फैली> { शून्य foo (एन एन) {} } फू foo = नई फू (); – Mik378