2012-01-05 27 views
5

ग्रहण का कहना है कि जेनेरिक प्रकार इरेज़र के कारण टाइप पैरामीटर के साथ उदाहरण के ऑपरेशन की अनुमति नहीं है।टी "उदाहरण के टी" की अनुमति क्यों नहीं है जहां टी एक प्रकार पैरामीटर है और टी एक चर है?

मैं मानता हूँ कि रनटाइम पर, कोई प्रकार की जानकारी रहती है। लेकिन कक्षा की निम्नलिखित सामान्य घोषणा पर विचार करें:

class SomeClass<T>{ 
    T t; 
    SomeClass(Object o){ 
     System.out.println(o instanceof T); // Illegal 
    } 
}   

रनटाइम पर, कोई टी मौजूद नहीं होगा! लेकिन अगर मैं इस प्रकार के इंटीजर को चालू करता हूं, तो संबंधित ऑब्जेक्ट में फ़ील्ड टी प्रकार इंटीजर होगा।

फिर, कारण है कि मैं टी के साथ एक चर जो रनटाइम पर पूर्णांक द्वारा बदला जा सकता है के प्रकार की जाँच नहीं कर सकते। और मैं वास्तव में कुछ ऐसा करूँगा जैसे "ओ इंस्टेंसफ इंटेगर"।

इसके तहत मामलों, एक प्रकार पैरामीटर मुसीबत पैदा कर सकता है के साथ instanceof की इजाजत दी, ताकि वह निषिद्ध है?

+7

जैसी कोई चीज़ नहीं होगी आप पहले ही कह चुके हैं "रनटाइम पर, कोई टी मौजूद नहीं होगा", तो ऐसा लगता है कि आप पहले से ही * टाइप एरर * के बारे में जानते हैं। तो मुझे यकीन नहीं है कि आप इस व्यवहार के बारे में उलझन में क्यों हैं? –

+1

सिर्फ इसलिए कि इसकी अनुमति नहीं है इसका मतलब यह है कि यह रूबल का कारण बन सकता है। टी एक सामान्य प्रकार है और वास्तव में कुछ भी हो सकता है, इसका उपयोग करके इसका मतलब केवल किसी भी तरह की समझ में आता है। – Peter

+0

[जावा: इंस्टेंसॉफ़ और जेनेरिक] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/1570073/java-instanceof-and-generics) – millimoose

उत्तर

3

कथन o instanceof T संकलित करने के बाद o instanceof Object होगा और क्योंकि सभी प्रकार ऑब्जेक्ट से प्राप्त होते हैं, यह हमेशा सत्य का मूल्यांकन करेगा। इस तरह के परीक्षणों को अनुमति देने से झूठी सकारात्मक परिणाम मिलेगा

0

सामान्य प्रकार के तर्क रनटाइम पर ज्ञात नहीं हैं, इसलिए कोई कक्षा नहीं है जिसके साथ आप तुलना कर सकते हैं। टी केवल संकलन समय पर जाना जाता है। जेनेरिक केवल डेवलपर को कोड लिखने में मदद करते हैं। लेकिन रनटाइम पर, तर्क केवल Object उदाहरण हैं।

4

आप कार्यावधि में टी की जरूरत है, तो आप क्रम में इसे प्रदान करने की जरूरत है। यह कक्षा < टी> जो टी होना है, को पारित करके किया जाता है।

class SomeClass<T> { 
    final T t; 

    public SomeClass(Class<T> tClass, T t) { 
     if(!tClass.isAssignableFrom(t.getClass()) throw new IllegalArgumentException("Must be a " + tClass); 
     this.t = t; 
    } 

    private SomeClass(T t) { 
     this.t = t; 
    } 

    public static <T> SomeClass<T> of(Class<T> tClass, T t) { 
     if(!tClass.isAssignableFrom(t.getClass()) throw new IllegalArgumentException("Must be a " + tClass); 
     return new SomeClass(t); 
    } 
} 

// doesn't compile 
SomeClass<Integer> intSomeClass = SomeClass.of(Integer.class, "one"); 

Class clazz = Integer.class; 
// compiles with a warning and throws an IAE at runtime. 
SomeClass<Integer> intSomeClass = (SomeClass<Integer>) SomeClass.of(clazz, "one"); 

// compiles and runs ok. 
SomeClass<Integer> intSomeClass = SomeClass.of(Integer.class, 1); 
3

type erasure की वजह से, यह कभी काम नहीं करता है। रनटाइम पर, आप केवल इतना जानते हैं कि आपकी कक्षा में एक प्रकार पैरामीटर T है, लेकिन किसी दिए गए उदाहरण के लिए यह किस प्रकार का नहीं है। तो आप यह निर्धारित नहीं कर सकते एक वस्तु के साथ शुरू करने के लिए प्रकार T की है या नहीं, क्योंकि आप नहीं जानते कि क्या T है, इसलिए नहीं कि यह मुसीबत में किसी प्रकार का कारण होगा।

आप क्रम की जांच की इस तरह करने की जरूरत है, तो स्पष्ट रूप से अपने वस्तु के लिए एक प्रकार टोकन पारित:

SomeClass(Object o, Class<T> type) { 
    System.out.println(type.isInstance(o)); 
} 
1

लेकिन अगर मैं प्रकार पूर्णांक के इस वर्ग का दृष्टांत, तो इसी वस्तु एक होगा प्रकार टी इंटीजर के क्षेत्र टी।

वास्तव में, ऐसा नहीं है। इसमें प्रकार का क्षेत्र t होगा। जैसा कि आपने कहा है, जेनेरिक लगभग पूरी तरह से वाक्य रचनात्मक चीनी हैं (अपवाद यह है कि जब आप एक सामान्य वर्ग का विस्तार करते हैं और एक प्रकार पैरामीटर निर्दिष्ट करते हैं, तो वर्ग वर्ग फ़ाइल में मेटाडेटा के रूप में रहता है)।

6

लेकिन अगर मैं प्रकार पूर्णांक के इस वर्ग का दृष्टांत, तो इसी ऑब्जेक्ट प्रकार पूर्णांक

नहीं के एक क्षेत्र टी होगा, ऐसा नहीं होगा। इसमें ऑब्जेक्ट का प्रकार होगा। बस जब भी आप इसे एक्सेस करते हैं, तो इसे एक इंटीजर पर डाला जाएगा।

SomeClass<Integer> c = new SomeClass<Integer>(); 
SomeClass untyped = (SomeClass)c; // Which type was it? 
SomeClass<String> stringTyped = (SomeClass<String>)untyped; // Now it's STRING?? 

काम करता है:

निम्नलिखित कोड पर विचार करें। आपको संकलक चेतावनियों का एक गुच्छा देता है, लेकिन काम करता है। क्योंकि फ़ील्ड टी वास्तव में ऑब्जेक्ट प्रकार का है और इसे किसी भी चीज़ पर डाला जा सकता है।

0

जावा में अपनी जेनेरिक्स का उपयोग कर "मिटाना", यह प्रकार की जांच और "संकलन समय" में प्रकार पैरामीटर जानकारी हटा सकते हैं, एहसास "रन टाइम" वहाँ केवल सीमाओं प्रकार पैरामीटर की , इसलिए "इंटीगर"

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