2015-07-04 4 views
5

समस्या एक सामान्य प्रतिबंध में है:हस्ताक्षर सूची <कक्षा <के साथ विधि को कार्यान्वित करना संभव है? जावा में एनोटेशन बढ़ाता है?

public List<Class<? extends Annotation>> getAnnotations() { 
    return new ArrayList<>(Arrays.asList(Override.class)); 
} 

रियल वापसी प्रकार ArrayList<Class<Override>>
विधि उम्मीद List<Class<? extends Annotation>>

Class<Override> की Class<? extends Annotation>
Class<? extends Annotation> c = Override.class; // अनुमति

ArrayList एक है एक उप-प्रकार है List का उप प्रकार, यदि तत्वों के प्रकार मेल खाते हैं:
List<? extends Number> l = new ArrayList<Integer>(); //

अनुमति बहरहाल, यह अनुमति नहीं है:

List<Class<? extends Annotation>> l = Arrays.asList(Override.class); 
List<Class<? extends Annotation>> l = new ArrayList<>(Arrays.asList(Override.class)); 

यह भी संभव है या Class वाइल्डकार्ड टूट रहे हैं?

+0

@kocko आपने किस जावा का उपयोग किया था? मेरे पास jdk1.7_079 है, यहां एक स्क्रीनशॉट है https://www.dropbox.com/s/p6gybp1jct19ehg/generics.jpg – AdamSkywalker

+1

मैंने इसके साथ थोड़ा सा खेला और मुझे लगता है कि मुझे कारण मिला है। मैं थोड़ी देर के बाद एक जवाब लिखूंगा। –

+1

परीक्षण से, जावा 7 की तरह दिखता है आपको स्थिर कॉल 'Arrays। > asList (ओवरराइड.क्लास) बढ़ाता है; '। जावा 8 के साथ मुझे –

उत्तर

2

मुझे लगता है कि यह jdk 1.7 प्रकार अनुमान प्रकृति की वजह से है।

आप पहले से ही जानते हैं, Arrays.asList(T ... elems) विधि सामान्य है, लेकिन हम शायद ही कभी स्पष्ट प्रकार पैरामीटर है जो हम साथ काम करने के विधि चाहते हैं निर्दिष्ट है और इस तरह हम संकलक का प्रकार निष्कर्ष सुविधा पर भरोसा

तो, जब संकलक देखता एक Arrays.asList(Override.class) बयान यह का अनुमान लगा होगा कि विधि के लिए प्रकार पैरामीटर Class<Override> साथ प्रतिस्थापित किया जाना चाहिए, यानी हम इस रूप में विधि का एक संस्करण होगा:

public List<Class<Override>> asList(Class<Override> ... elems) 

हालांकि, आप स्पष्ट रूप से

को विधि के लिए प्रकार पैरामीटर सेट अगर ,

public List<? extends Annotation> asList(Class<? extends Annotation> ... elems) 

अब इस ठीक संकलित कर देगा के बाद से Class<? extends Annotation> संगत है:

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

हालांकि, अधिक दिलचस्प सवाल

क्यों List<Class<Override>>List<Class<? extends Annotation>> साथ संगत नहीं है करने के लिए चला जाता है?

java.lang.Class एक final एक है, जो निम्नलिखित दो प्रश्नों के उत्तर में मदद मिलेगी, संयोजन, जिनमें से ऊपर सवाल का जवाब नहीं है।:)

तो,

  • क्या एक List<Class<Override>> मतलब है?

List<Class<Override>> का अर्थ है कि हम केवल Class<Override> के उदाहरण जोड़ सकते हैं और सूची में कुछ भी नहीं। जो महान है, यह जानकर कि हम Class<Override> उप-वर्ग भी जोड़ नहीं सकते हैं, क्योंकि Class प्रकार final है।

  • List<Class<? extends Annotation>> का क्या अर्थ है?

List के इस प्रकार के वर्गों की सूचियों की एक पूरी परिवार का प्रतिनिधित्व करता है, जो सभी के Annotation प्रकार, कि हम सफलतापूर्वक किसी भी टिप्पणी का प्रकार (उदाहरण के लिए, SuppressWarnings.class, Override.class के लिए जोड़ सकते हैं, जिसका मतलब है की उपवर्गों हैं, Documented.class , आदि) सूची में।

मान देता है कि निम्न उदाहरण वास्तव में सही था:

List<Class<Override>> overrides = Arrays.asList(Override.class); 
List<Class<? extends Annotation>> annotations = new ArrayList<>(); 
annotations = overrides; 
annotations.add(SuppressWarnings.class); //HUGE PROBLEM 
annotations.add(Documented.class); //ANOTHER HUGE PROBLEM 

दो विशाल समस्याओं तथ्य यह है कि हम overrides करने के लिए कुछ गैर Override उदाहरणों को जोड़ने के लिए, जो बहुत गलत है कोशिश कर रहे हैं से आते हैं।

हमारे पास पर्याप्त पर्याप्त कंपाइलर है जो वास्तव में ऐसी संभावित समस्याओं का पता लगा सकता है और एक संकलन-समय त्रुटि फेंकने का तरीका है जिससे हम इसे करने से रोक सकते हैं।

और जानकारी:

+0

आपके द्वारा खर्च किए गए समय के लिए धन्यवाद। पहला भाग बताता है कि हम अभी टाइप डिटेक्शन के साथ धोखेबाज हैं। जहां तक ​​मुझे पता है, जावा 8 में कोई बदलाव है, जो असाइन स्टेटमेंट के बाएं हिस्से का विश्लेषण करता है, इसलिए यह इस समस्या को हल करता है। दूसरा भाग संग्रह में क्लासिक सबटाइपिंग समस्या को संदर्भित करता है, मैं उससे परिचित हूं। आइए कुछ दिनों तक प्रतीक्षा करें कि क्या हम यहां कुछ चूक गए हैं, और यदि सबकुछ ठीक है, तो मैं इसे स्वीकार करूंगा। धन्यवाद फिर से :) – AdamSkywalker

+0

आपका स्वागत है। :) –

1

ArrayList, एक सूची की एक उप-प्रकार है अगर तत्वों के प्रकार से मेल खाते हैं:

List<? extends Number> l = new ArrayList<Integer>(); // allowed 

हाँ, पर अपने उदाहरण में तत्व प्रकार मेल नहीं खाते:

List<Class<? extends Annotation>> l = new ArrayList<Class<Override>>(); 

दी, Class<Override>Class<? extends Annotation> की एक उप-प्रकार है, लेकिन List<String> जैसे List<Object> की एक उप प्रकार नहीं है, List<Class<Override>>List<Class<? extends Annotation>> की एक उप प्रकार नहीं है। यह List<? extends Class<? extends Annotation>> का उपप्रकार होगा, हालांकि।

यह कहा गया है कि आपका कोड संकलित नहीं करने का कारण यह है कि जावा 7 में, टाइप कॉन्फ़्रेंस विधि के रिटर्न प्रकार को ध्यान में रखता है जब रिटर्न स्टेटमेंट की अभिव्यक्ति के प्रकार का उल्लंघन होता है, तो यह सबसे विशिष्ट प्रकार के लिए डिफ़ॉल्ट होता है

Arrays.asList(Override.class) 

साकार नहीं कि वापसी कथन केवल एक और अधिक लचीला प्रकार के साथ संकलन होगा करने के लिए आवंटित किया जा सकता है (जावा 8 प्रकार निष्कर्ष होशियार है, Btw)।

Arrays.<Class<? extends Annotation>(Override.class); 

या पहले एक स्थानीय चर को बताए द्वारा जावा 7 के प्रकार निष्कर्ष एक संकेत दे::

List<Class<? extends Annotation>> list = Arrays.asList(Override.class); 
return list; 

या

को विधि वापसी प्रकार बदलने के एक वैकल्पिक हल स्पष्ट रूप प्रकार तर्क निर्दिष्ट करने के लिए है
List<? extends Class<? extends Annotation>> getAnnotations() 

इसलिए अनुमानित प्रकार कोई फर्क नहीं पड़ता।

+0

अंतिम कोड पंक्ति हास्यास्पद लगती है, लेकिन काम करता है, lol – AdamSkywalker

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