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>
को कास्ट करने के लिए सही प्रकार प्राप्त करने के लिए पर है। कंपाइलर चेतावनी दबाया जा सकता है, लेकिन क्या यह उचित है? क्या कोई परिदृश्य है जहां यह कास्ट सच नहीं है?
कक्षा ऐसी विधियां नहीं हो सकती हैं जो वास्तव में टी के किसी भी सुपरक्लास का उपयोग करती हैं, लेकिन, एक प्रकार का प्रतिनिधित्व करते हैं, यह सुपर प्रकारों के बारे में जानकारी प्रदान करने का दावा करता है। यदि आप क्लास की getSuperclass() विधि देखते हैं, तो इसका रिटर्न प्रकार 'कक्षा super T>' है। यह मामला है, यह getInterfaces() के लिए मेरे समान लौटने के लिए और भी उपयुक्त लगता है। यदि वे सोच रहे थे, जैसा कि आप सुझाव देते हैं, कि कक्षा कभी भी बाध्य वाइल्डकार्ड की अनुमति देकर उन तरीकों में से किसी भी तरीके का उपयोग नहीं करेगी, कक्षा क्यों एक सुपरक्लास को ' super T>' के रूप में निर्दिष्ट किया जाएगा? –
sager
यह शायद एपीआई डिजाइनर द्वारा एक गलती है। मैं बहस कर रहा हूं कि इससे कोई फर्क नहीं पड़ता। – irreputable
मैंने इस तरीके से कक्षा का उपयोग करने का एक ठोस मामला जोड़ा है। यह अब खोज में है। – sager