2011-11-18 13 views
12

java.lang.Class की getInterfaces() विधि वापसी क्लास <?> [] और कक्षा <? super T> [] क्यों नहीं है?

बस एक उदाहरण के रूप में निम्न एप्लिकेशन की समीक्षा करें (सवाल स्पष्ट करने के लिए, 'टी' एक प्रकार पैरामीटर कक्षा में घोषित करने के लिए संदर्भित करता है):

public class TestClass { 

    interface InterfaceA{} 

    interface InterfaceB{} 

    interface InterfaceC{} 

    class ClassA implements InterfaceA, InterfaceB, InterfaceC{} 


    public static void main(String[] args){  

     Class<? super ClassA> superClass1 = ClassA.class; 
     Class<? super ClassA> superclass2 = InterfaceA.class; 
     Class<? super ClassA> superclass3 = InterfaceB.class; 
     Class<? super ClassA> superclass4 = InterfaceC.class; 

     for(Class<?> clazz : ClassA.class.getInterfaces()){ 
      System.out.println(clazz.getName()); 
     } 
    } 
} 

उत्पादन एक उम्मीद होती है क्या है :

TestClass$InterfaceA 
TestClass$InterfaceB 
TestClass$InterfaceC 

तो, ऊपर इस उदाहरण पर आधारित है, हम देख सकते हैं संकलक स्वीकार करता है कि कि InterfaceA करता मिलने वें वाइल्डकार्ड की ई सीमाएं, जैसा कि अन्य सभी इंटरफेस करते हैं।

Intuitively, मैं सुरक्षित रहने के लिए निम्नलिखित उम्मीद होती है, लेकिन यह नहीं है:

Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces(); 

संकलक एक चेतावनी देता है, क्योंकि हस्ताक्षर कहना है कि यह वर्ग रिटर्न; निम्नलिखित हालांकि, कक्षा के लिए जावाडोक राज्यों: इस वस्तु एक वर्ग का प्रतिनिधित्व करता है

हैं, वापसी मान एक सरणी युक्त वस्तुओं वर्ग द्वारा कार्यान्वित सभी इंटरफ़ेस का प्रतिनिधित्व करता है।

'यह ऑब्जेक्ट' हमारे मामले में ClassA पर संदर्भित करता है। इस बयान के आधार पर, अगर हम कहते हैं:

ClassA.class.getInterfaces() 

तो हम जानते हैं, तार्किक, कि लौट आए सरणी में हर Class<?>ClassA का एक सुपर प्रकार के लिए एक संदर्भ में शामिल होंगे।

संदर्भ की एक अतिरिक्त अंक के रूप में:

जावा भाषा संदर्भ, तीसरा संस्करण से:

एक वर्ग जरूरी सभी इंटरफ़ेस है कि इसके प्रत्यक्ष सुपर-क्लास और प्रत्यक्ष superinterfaces कर लागू करता है। यह (एकाधिक) इंटरफेस विरासत किसी भी कार्यान्वयन को साझा किए बिना ऑब्जेक्ट्स (एकाधिक) सामान्य व्यवहार का समर्थन करने की अनुमति देता है।

इस और विनिर्देश के अन्य भागों पढ़ना, मुझे लगता है कि होता है कि किसी भी वर्ग या एक वर्ग T द्वारा इंटरफ़ेस कार्यान्वित या exteneded सीमा <? super T> में गिर जाएगा।

संपादित:

यह सुझाव दिया है मेरे सवाल के लिए कोई ठोस कारण नहीं है। मैं एक उदाहरण प्रदान करेगा:

1 import java.util.Map; 
2 import java.util.HashMap; 
3  
4 public class MapWrapper<T> { 
5  private final Map<Class<?>, OtherClass<T,?>> map = new HashMap <Class<?>, OtherClass<T,?>>(); 
6  
7  public <W> void addToMap(Class<W> type, OtherClass<T,? super W> otherClass){ 
8   map.put(type, otherClass); 
9  } 
10  
11  public <W> OtherClass<T,? super W> getOtherClassForAnyInterface(Class<W> type){ 
12   if(type.getInterfaces()!=null){ 
13    for(Class<?> interfaceType : type.getInterfaces()){ 
14     // Here, a cast is necessary. It throws a compiler warning for unchecked operations (rightfully so) 
15     OtherClass<T,? super W> otherClass = (OtherClass<T,? super W>)getOtherClassForInterface(interfaceType); 
16     if(null!=otherClass){ 
17      return otherClass; 
18     } 
19    } 
20   } 
21   return null; 
22  } 
23  
24   
25  public class OtherClass<T,V> {} 
26  
27 } 

समस्या लाइन 15. आप <? super W> को कास्ट करने के लिए सही प्रकार प्राप्त करने के लिए पर है। कंपाइलर चेतावनी दबाया जा सकता है, लेकिन क्या यह उचित है? क्या कोई परिदृश्य है जहां यह कास्ट सच नहीं है?

उत्तर

5

आप सही हैं, वापसी का प्रकार अधिक विशिष्ट हो सकता है।

हालांकि, Class<? super X> वैसे भी बहुत उपयोगी नहीं है। अधिकांश उपयोगों के लिए Class<?> पर्याप्त है।

हम एक घोषणा G<T>, G<? super X> के लिए उपयोगी होने के लिए है, तो आमतौर पर G तरीकों कि T स्वीकार होना चाहिए। उदाहरण के लिए, List<T> में add(T) है। तो List<? super X> उपयोगी है, हम (प्रकार X की जा रही है x) उस पर add(x) फोन

Class ऐसी विधियां नहीं कर सकते हैं।

क्या आपके पास एक विश्वसनीय उपयोग केस है जिसे आपको वास्तव में Class<? super ClassA> की आवश्यकता है?

+2

कक्षा ऐसी विधियां नहीं हो सकती हैं जो वास्तव में टी के किसी भी सुपरक्लास का उपयोग करती हैं, लेकिन, एक प्रकार का प्रतिनिधित्व करते हैं, यह सुपर प्रकारों के बारे में जानकारी प्रदान करने का दावा करता है। यदि आप क्लास की getSuperclass() विधि देखते हैं, तो इसका रिटर्न प्रकार 'कक्षा ' है। यह मामला है, यह getInterfaces() के लिए मेरे समान लौटने के लिए और भी उपयुक्त लगता है। यदि वे सोच रहे थे, जैसा कि आप सुझाव देते हैं, कि कक्षा कभी भी बाध्य वाइल्डकार्ड की अनुमति देकर उन तरीकों में से किसी भी तरीके का उपयोग नहीं करेगी, कक्षा क्यों एक सुपरक्लास को '' के रूप में निर्दिष्ट किया जाएगा? – sager

+0

यह शायद एपीआई डिजाइनर द्वारा एक गलती है। मैं बहस कर रहा हूं कि इससे कोई फर्क नहीं पड़ता। – irreputable

+0

मैंने इस तरीके से कक्षा का उपयोग करने का एक ठोस मामला जोड़ा है। यह अब खोज में है। – sager

0

फिर, मान लीजिए कि आप इस सामान्य विधि घोषणा की है कि करते हैं:

एक गैर सरणी उदाहरण

<T super Integer> void add(T number) // hypothetical! currently illegal in Java

और आप इन चर घोषणाओं है:

Integer anInteger Number aNumber Object anObject String aString

<T super Integer> (यदि यह कानूनी है) के साथ आपका इरादा यह है कि यह सब कुछ होना चाहिए डब्ल्यू add(anInteger), और add(aNumber), और निश्चित रूप से add(anObject), लेकिन add(aString) नहीं। खैर, स्ट्रिंग एक ऑब्जेक्ट है, इसलिए add(aString) अभी भी संकलित होगा।

प्रतिलिपि से: Stack Overflow - Bounding generics with 'super' keyword

यह मुझे मदद की। आपकी मदद भी कर सकते हैं :)

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