2008-10-02 20 views
19

के लिए मिलान मिलान करें मेरे पास निम्न कोड है जो संकलित नहीं होगा और हालांकि इसे संकलित करने का कोई तरीका है, मैं समझना चाहता हूं कि यह संकलन क्यों नहीं कर रहा है। क्या कोई मुझे विशेष रूप से प्रबुद्ध कर सकता है कि मुझे त्रुटि संदेश क्यों मिलता है, मैं अंत में पोस्ट करूंगा?क्लास जेनिक्स

public class Test { 
    public static void main(String args[]) { 
     Test t = new Test(); 
     t.testT(null); 
    } 

    public <T extends Test> void testT(Class<T> type) { 
     Class<T> testType = type == null ? Test.class : type; //Error here 
     System.out.println(testType); 
    } 
} 

Type mismatch: cannot convert from Class<capture#1-of ? extends Test> to Class<T>

Class<T> इस के लिए Test.class का निर्माण करके एक Unchecked cast चेतावनी के साथ संकलित करता है तथा पूरी तरह से चलाता है।

उत्तर

22

कारण यह है कि Test.class प्रकार कक्षा < टेस्ट > की है। आप कक्षा < टेस्ट > प्रकार के संदर्भ को कक्षा < टी > के प्रकार के संदर्भ में निर्दिष्ट नहीं कर सकते क्योंकि वे एक ही चीज़ नहीं हैं। लेकिन यह काम करता है:

Class<? extends Test> testType = type == null ? Test.class : type; 

वाइल्डकार्ड दोनों कक्षा < टी > और कक्षा < टेस्ट > संदर्भ testType को सौंपा जा करने के लिए अनुमति देता है।

जावा जेनिक्स व्यवहार के बारे में जानकारी का एक टन Angelika Langer Java Generics FAQ पर जानकारी है। मैं वहां कुछ जानकारी के आधार पर एक उदाहरण प्रदान करूंगा जो Number कक्षा विरासत जावा के कोर एपीआई का उपयोग करता है।

public <T extends Number> void testNumber(final Class<T> type) 

यह सफलतापूर्वक संकलन होने के लिए निम्नलिखित बयानों के लिए अनुमति देने के लिए है:

testNumber(Integer.class); 
testNumber(Number.class); 

लेकिन निम्नलिखित संकलन नहीं होगा:

testNumber(String.class); 

निम्न विधि पर विचार करें

अब इन बयानों पर विचार करें:

Class<Number> numberClass = Number.class; 
Class<Integer> integerClass = numberClass; 

दूसरी पंक्ति संकलित करने और इस त्रुटि को Type mismatch: cannot convert from Class<Number> to Class<Integer> उत्पन्न करने में विफल रहता है। लेकिन IntegerNumber बढ़ाता है, तो यह क्यों विफल हो जाता है? इन अगले दो बयानों को देखने के लिए देखें:

Number anumber = new Long(0); 
Integer another = anumber; 

यह देखना बहुत आसान है कि दूसरी पंक्ति यहां संकलित क्यों नहीं होती है। आप Number का एक प्रकार Integer के चर के लिए आवंटित नहीं कर सकते हैं क्योंकि Number उदाहरण एक संगत प्रकार की गारंटी देने का कोई तरीका नहीं है। इस उदाहरण में Number वास्तव में Long है, जिसे निश्चित रूप से Integer पर असाइन नहीं किया जा सकता है। असल में, त्रुटि भी एक प्रकार का मेल नहीं है: Type mismatch: cannot convert from Number to Integer

नियम यह है कि एक आवृत्ति को एक चर के लिए असाइन नहीं किया जा सकता है जो कि उदाहरण के प्रकार का उप-वर्ग है क्योंकि कोई गारंटी नहीं है कि संगत है।

जेनरिक एक समान तरीके से व्यवहार करते हैं।जेनेरिक विधि हस्ताक्षर में, T यह इंगित करने के लिए केवल प्लेसहोल्डर है कि विधि कंपाइलर को क्या अनुमति देती है। जब संकलक testNumber(Integer.class) से मुठभेड़ करता है तो यह Integer के साथ T को अनिवार्य रूप से बदल देता है।

वाइल्डकार्ड, अतिरिक्त लचीलापन जोड़ने के रूप में निम्नलिखित संकलन होगा:

Class<? extends Number> wildcard = numberClass; 

Class<? extends Number> के बाद से किसी भी प्रकार है कि एक Number या Number का एक उपवर्ग इस पूरी तरह से कानूनी और कई परिस्थितियों में संभावित रूप से उपयोगी है इंगित करता है।

public class SubTest extends Test { 
    public static void main(String args[]) { 
    Test t = new Test(); 
    t.testT(new SubTest()); 
    } 
} 

अब, जब मैं testT लागू, प्रकार पैरामीटर <T>SubTest है, जिसका अर्थ है चर testType एक Class<SubTest> है:

+0

मैं समझना चाहता हूं कि टाइप क्लास और प्रकार क्लास के चर के संदर्भ में आपका क्या मतलब है। क्या आप जावा के संदर्भ में बात कर रहे हैं और यह कैसे संबंधित है? –

+0

जावा में, एक वैरिएबल जो कि आदिम प्रकार के अलावा कुछ भी है, एक संदर्भ है। मैं असाइनमेंट के बाएं हाथ के पक्ष को संदर्भित करने के लिए शब्द परिवर्तक का उपयोग कर रहा हूं और दाएं हाथ के संदर्भ में संदर्भ संदर्भ का संदर्भ देता हूं। – laz

+0

यदि 'टी' को 'टेस्ट' का विस्तार करना चाहिए, तो आप कक्षा ' कक्षा 'क्यों निर्दिष्ट नहीं कर सकते? 'कक्षा ' कक्षा <टी का मामला टेस्ट> ', polymorphically विस्तारित नहीं है? –

1

सशर्त निकालें और त्रुटि एक छोटे से अच्छे है ...

public class Test { 
    public static void main(String args[]) { 
     Test t = new Test(); 
     t.testT(null); 
    } 

    public <T extends Test> void testT(Class<T> type) { 
    Class<T> testClass = Test.class; 
     System.out.println(testClass); 
    } 
} 


Test.java:10: incompatible types 
found : java.lang.Class<Test> 
required: java.lang.Class<T> 
     Class<T> testClass = Test.class; 
4

मान लीजिए मैं टेस्ट का विस्तार। Test.class प्रकार Class<Test> है, जो Class<SubTest> के प्रकार के चर के लिए असाइन करने योग्य नहीं है।

को Class<? extends Test> के रूप में घोषित करने का सही समाधान है; Class<T> पर कास्टिंग एक वास्तविक समस्या छुपा रहा है।

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