2010-02-23 4 views
21

जावा जेनरिक की मेरी स्पष्ट रूप से गलत समझ अब तक थी, कि टाइप एरर सभी प्रकार की जानकारी को हटा देता है जैसे रनटाइम पर कुछ भी नहीं बचा है। हाल ही में मैंने एक कोड खंड पर ठोकर खाई जहां मुझे खुद से पूछना पड़ा: यह हैक कैसे काम करता है? सरलीकृत, यह प्रस्तुत करता है के रूप में:रनटाइम पर जावा में सभी प्रकार की जानकारी मिटाई क्यों नहीं जाती है?

import java.lang.reflect.ParameterizedType; 
import java.lang.reflect.Type; 

public abstract class SuperClass<T> { 

    private final Type type; 

    protected SuperClass(){ 
     ParameterizedType parameterizedType = 
       (ParameterizedType) getClass().getGenericSuperclass(); 
     type = parameterizedType.getActualTypeArguments()[0]; 
    } 

    public void tellMyType(){ 
     System.out.println("Hi, my type parameter is " + type); 
    }  
} 

और

public class Example { 

    public static void main(String[] args) { 
     SuperClass sc = new SuperClass<Integer>(){}; 
     sc.tellMyType(); 
    } 
} 

Hi, my type parameter is class java.lang.Integer में मुख्य कक्षा के परिणाम निष्पादित।

हम यहां क्या देख सकते हैं, टी की प्रकार की जानकारी रनटाइम पर भी उपलब्ध है, जो मेरी प्रारंभिक समझ के विपरीत है।

तो मेरा सवाल है: संकलक इसे क्यों रखता है? क्या यह कुछ आंतरिक जेवीएम व्यवहार के लिए आवश्यक है या क्या इस प्रभाव के लिए कोई उचित स्पष्टीकरण है?

उत्तर

16
http://www.artima.com/weblogs/viewpost.jsp?thread=208860 से

:

यह पता चला है कि जब JVM एक सामान्य वर्ग की घटनाओं के लिए वास्तविक प्रकार तर्क को ट्रैक नहीं करेगा, यह सामान्य वर्ग के उपवर्गों के लिए वास्तविक प्रकार तर्क ट्रैक करता है । दूसरे शब्दों में, जबकि एक नया ArrayList<String>() वास्तव में सिर्फ एक नई ArrayList() रनटाइम पर, अगर एक वर्ग फैली ArrayList<String>, तो JVM जानता है कि StringList के प्रकार पैरामीटर के लिए वास्तविक प्रकार तर्क है।

आपके मामले में, आप पैरामीटरयुक्त प्रकार का अज्ञात सबक्लास बना रहे हैं, इसलिए प्रकार की जानकारी बरकरार रखी जाती है। गहराई से स्पष्टीकरण के लिए आलेख देखें।

+0

संक्षिप्त टिप्पणी: यदि आपका उप-वर्ग सामान्य रूप से जेनेरिक प्रकार को पास करता है (जैसा कि 'पब्लिक क्लास सुपरलिस्ट में ऐरेलिस्ट ') बढ़ाता है, उदाहरण कोड (बिना किसी अज्ञात कक्षाओं के) के आउटपुट" हाय, मेरा टाइप पैरामीटर टी "होगा – sfussenegger

+0

तो अगर उन्होंने 'मुख्य' में '{}' को छोड़ दिया था (जो संभवतया कन्स्ट्रक्टर को सार्वजनिक रूप से बदलने की आवश्यकता होगी), तो तथ्य यह है कि टाइप पैरामीटर 'इंटेगर' रनटाइम पर खो गया होगा? – MatrixFrog

1

This FAQ on type erasure मदद कर सकता है।

+1

क्या आपने यह जांच की कि क्या यह करता है? – danben

+0

मुझे कैसे पता चलेगा कि यह लार्स की मदद करता है? –

14

प्रकार पैरामीटर (यानी वस्तु का एक प्रकार बनाया जा रहा) केवल गतिशील प्रकार से मिटाया जा रहा है:

Object o = new ArrayList<String>(); // String erased 

यह (यानी क्षेत्र, तर्क स्थिर प्रकार में बनाए रखा और प्रकार, throws खंड, सुपर क्लास लौट रहा है और superinterface घोषणाओं):

class Test implements Superclass<String> { // String retained 
    // Accessible via Class.getGenericSuperclass() 

    private List<Integer> l; // Integer retained (via Field.getGenericType()) 

    public void test(List<Long> l) {} // Long retained (via Method.getGenericParameterTypes()) 

    // Character retained (via Method.getGenericReturnType()) 
    public List<Character> test() { return null; } 
} 

आपके मामले में, आप SuperClass<Integer> की एक अनाम उपवर्ग बनाते हैं, तो प्रकार पैरामीटर सुपर क्लास घोषणा में बरकरार है।

3

Google Guice रनटाइम पर सामान्य कक्षाओं का प्रतिनिधित्व करने के लिए TypeLiteral एस बनाने के लिए इसका उपयोग करता है। उदाहरण के लिए

TypeLiteral<List<String>> list = new TypeLiteral<List<String>>() {}; 

इस्तेमाल किया जा सकता है, लेकिन

Class<List<String>> list = List<String>.class; 

संकलन नहीं होंगे।

तकनीक को 'सुपर टाइप टोकन' के रूप में जाना जाता है (इस विषय पर Neal Gafter's article देखें)।

0

मुझे पैरामेटेराइज्ड टाइप मेरे लिए काम नहीं कर सका (मैं सुपर क्लास का कोड नहीं बदल सका)। हालांकि, निम्नलिखित सरल कोड ठीक काम करते थे:

try 
    { 
    SuperClass<Integer> castSc = (SuperClass<Integer>)sc; 
    // Do what you want to do if generic type is Integer... 
    } 
catch (ClassCastException ignored) 
    { 
    } 
संबंधित मुद्दे

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