2011-12-08 3 views
9

मैं सिर्फ एक खाली List तत्व है जो प्रकार String का माना जाता है कि कर रहे हैं के साथ पाने के लिए इस fine looking syntaxजेनेरिक प्रकार की कक्षा कैसे प्राप्त करें जब इसका कोई पैरामीटर न हो?

Collections.<String>emptyList() 

बारे में सीखा। जावा के स्रोत इस तरह दिखता है: अगर मैं इस तरह से जहां सामान्य प्रकार पैरामीटर सूची में दिखाई नहीं देता में एक विधि कोड

public static final List EMPTY_LIST = new EmptyList<Object>(); 
: 
public static final <T> List<T> emptyList() { 
    return (List<T>) EMPTY_LIST; 
} 

अब, वहाँ किसी भी तरह से मैं कैसे वास्तविक वर्ग कि T हो जाता है का उपयोग कर सकते है?

मैं कह रहा हूँ, अब कोड करने के लिए करने के लिए अपने दृष्टिकोण एक ही बात

private <T> T get(String key, Class<T> clazz) { 
    // here I can do whatever I want with clazz, e.g.: 
    return clazz.cast(value); 
} 

हो गया होता अगर मैं clazz -parameter मैं cast() ऐसा करने में सक्षम नहीं होगा हटा दिया। जाहिर है मैं

return (T) value; 

कर सकता है, लेकिन है कि मुझे हमेशा की तरह चेतावनी Type safety: Unchecked cast from Object to T देता है। ठीक है, @SuppressWarnings("unchecked") यहां मदद करता है, लेकिन असल में मैं विधि के इच्छित रिटर्न प्रकार के साथ कुछ करना चाहता हूं। मैं एक स्थानीय चर

T retValue; 

जोड़ देते हैं तो मैं null मदद नहीं करता है कुछ के साथ यह आरंभ करना होगा,। इसे

@SuppressWarnings("unchecked") 
T retValue = (T) value; 

मैं असाइन कर सकता हूं, उदाहरण के लिए

retValue.getClass().getName() 

लेकिन कलाकारों में विफल रहता है के बारे में मैं T फिर से कोई जानकारी के साथ खत्म हो रहे हैं।

चूंकि जावा (या कम से कम मेरे जावा 6) में रनटाइम के दौरान जेनेरिक जानकारी नहीं है, इसलिए मैं वर्तमान में ऐसा करने का तरीका नहीं सोच सकता। क्या उधर रास्ता है? या क्या मुझे यहां अपने "पुराने" दृष्टिकोण से चिपकना है?

कृपया ध्यान दें कि मैंने जो उदाहरण दिया है वह बहुत सरल है और यह बहुत समझ में नहीं आता है। मैं यहां और अधिक जटिल चीजें करना चाहता हूं, लेकिन यह दायरे से बाहर है।

+0

[इस सवाल] (http://stackoverflow.com/questions/2434041/instantiating-generics-type-in-java) –

+0

@NitzanVolman: एक निश्चित सीमा तक आप सही हैं, लेकिन यह नहीं है पूरी तरह। – sjngm

उत्तर

5

यदि आप जेनेरिक प्रकार रनटाइम पर चाहते हैं तो आपको इसे किसी फ़ील्ड के रूप में रखना होगा या प्रकार के विशिष्ट संयोजन के लिए एक प्रकार का उप-वर्ग बनाना होगा।

उदा।

List<String> list = new ArrayList<String>() {}; // creates a generic sub-type 
final Class type = (Class) ((ParameterizedType) list.getClass() 
          .getGenericSuperclass()).getActualTypeArguments()[0]; 
System.out.println(type); 

प्रिंट

class java.lang.String 
+0

यह अच्छा है, मुझे इसके बारे में पता नहीं था। –

+1

यानी आप सामान्य श्रेणी के वर्ग नहीं प्राप्त कर सकते हैं, लेकिन एक सुपर क्लास (और सुपर इंटरफेस) के प्रकार प्राप्त कर सकते हैं –

+0

@ पीटर Lawrey: Whow, धन्यवाद। हालांकि, अगर मैं 'सूची सूची = नई ArrayList () {} का उपयोग करता हूं, तो यह काम नहीं करता है। 'getActualTypeArguments() [0] '' sun.reflect.generics.reflectiveObjects.TypeVariableImpl' है। क्या इसका कोई मतलब है? – sjngm

1

जैसा कि आपने बताया है, जावा जेनरिक केवल समय का निर्माण कर रहे हैं। वे रन टाइम पर उपयोग नहीं किया जाता है।

इस वजह से, आप जिस पुराने दृष्टिकोण का उपयोग कर रहे थे वह इसे पूरा करने का एकमात्र तरीका होगा।

4

दुर्भाग्य से आप नहीं कर सकते हैं। रनटाइम में सभी जेनेरिक और टाइप पैरामीटर मिटा दिए जाते हैं। तो क्रम में अपने T के प्रकार Object

+2

सहमत हैं, मेरे पास 'निजी टी प्राप्त करने की कई विधियां हैं (स्ट्रिंग कुंजी, कक्षा क्लैज) इस वजह से। – Dave

2

retValue.getClass().getName() हमेशा वस्तु के क्रम प्रकार और नहीं पैरामीटर प्रकार के वर्ग के नाम वापस आ जाएगी बस है।

यदि आप पैरामीटर वर्ग को पकड़ना चाहते हैं, तो आपके पहले समाधान का उपयोग करने के अलावा कोई अन्य तरीका नहीं है। (यानी, कक्षा वस्तु को स्पष्ट रूप से पास करें।)

+0

आप सही हैं, यह एक और दुष्प्रभाव होता जो मैं नहीं करना चाहता था। – sjngm

-2

मुझे पता टी से Class<?> प्राप्त करने के लिए एक समाधान है कि वहाँ:

Action<String> myAction = new Action<String>(); 

getGenericType(myAction); 

मैं:

public class Action<T>{ 
} 

public Class<?> getGenericType(Object action) throws ClassNotFoundException{ 
    Type type = 
    ((ParameterizedType)action.getClass().getGenericSuperclass()) 
     .getActualTypeArguments()[0]; 
    String sType[] = type.toString().split(" "); 

    if(sType.length != 2) 
     throw new ClassNotFoundException(); 

    return Class.forName(sType[1]); 
} 

उपरोक्त कोड का उपयोग प्राइम के साथ इसका परीक्षण नहीं किया जीवित प्रकार (int, बाइट, बूलियन)।

मुझे लगता है कि यह बहुत तेज़ नहीं है, लेकिन आपको Class<?> को कन्स्ट्रक्टर को पास करने की आवश्यकता नहीं है।

संपादित करें:

ऊपर उपयोग क्योंकि सामान्य सुपर क्लास Action<String> लिए उपलब्ध नहीं है, सही नहीं है। जेनेरिक सुपर क्लास केवल विरासत वर्ग के लिए उपलब्ध होगी जैसे class ActionWithParam extends Action<String>{}। यही कारण है कि मैंने अपना दिमाग बदल दिया और अब मैं कन्स्ट्रक्टर को क्लास पैरामीटर पास करने का सुझाव देता हूं। सुधार के लिए newacct के लिए धन्यवाद।

+0

यह गलत है .. – newacct

+0

क्या गलत है? मुझे पता है कि लेंस जांच और पुनरावृत्ति होना चाहिए ((पैरामीटरेट टाइप टाइप) action.getClass()। GetGenericSuperclass())। GetActualTypeArgum ents() और "वर्ग" के साथ sType [0] का संपीड़न प्राप्त करें। मैं इसे अपने कस्टम रिमोट विधि आमंत्रण में उपयोग करता हूं और यह काम करता है। अगर कुछ और गलत है तो कृपया मुझे कुछ संकेत दें। – ivanesko

+0

दिखाया गया कोड "काम" नहीं करता है – newacct

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