2010-06-07 21 views
8

का उपयोग करके पैरामीटरयुक्त प्रकार ऑब्जेक्ट बनाना यह एक बेवकूफ सवाल हो सकता है, लेकिन मैंने अभी एक प्रश्न देखा है how to create a Type variable for a generic type। सर्वसम्मति यह प्रतीत होती है कि आपके पास उस प्रकार की लौटने वाली डमी विधि होनी चाहिए, और फिर इसे प्राप्त करने के लिए प्रतिबिंब का उपयोग करें (इस मामले में वह Map<String, String> चाहता था)। कुछ इस तरह:अज्ञात वर्ग

public Map<String, String> dummy() { throw new Error(); } 

Type mapStringString = Class.forName("ThisClass").getMethod("dummy").getGenericReturnType(); 

मेरा प्रश्न है, इस्तेमाल किया प्रतिबिंब नहीं होने इतना, तुम बस की तरह कुछ नहीं कर सका:

Type mapStringString = new ParameterizedType() { 
    public Type getRawType() { 
     return Map.class; 
    } 

    public Type getOwnerType() { 
     return null; 
    } 

    public Type[] getActualTypeArguments() { 
     return new Type[] { String.class, String.class }; 
    } 
}; 

चाहेंगे इस काम करता है? यदि नहीं, तो क्यों नहीं? और खतरों में से कुछ/समस्याओं क्या हैं अगर यह (Integer<String> जैसे कुछ प्रकार वापस जाने के लिए सक्षम किया जा रहा है जो स्पष्ट रूप से संभव नहीं है के अलावा है।

+0

मैं आपके प्रस्तावित समाधान की अनुमति देने की कोशिश कर रहा हूं: कच्चे से पैरामीटरेटेड प्रकार प्राप्त करें संकलन समय पर आपूर्ति किए गए प्रकार पैरामीटर का प्रकार और सूची। क्या आपको ऐसा करने का दूसरा तरीका मिला? – user48956

उत्तर

6

सुनिश्चित करें कि आप कर सकते थे, और सबसे अनुप्रयोगों के लिए यह शायद पर्याप्त होगा।

हालांकि, पहली विधि का उपयोग करके, आपको एक और परिष्कृत वस्तु मिलती है। उदाहरण के लिए कहें कि आप दूसरी विधि का उपयोग करते हुए type1 ऑब्जेक्ट बनाते हैं, और type2 दूसरी विधि का उपयोग करते हैं। फिर type1.equals(type2) सत्य वापस आ जाएगा (क्योंकि पहली विधि किसी ऑब्जेक्ट को लौटाती है बराबर बराबर लागू करता है) लेकिन type2.equals(type1) झूठी वापसी करेगा (क्योंकि दूसरी विधि में, आपने बराबर-विधि को ओवरराइड नहीं किया है, और 0 से कार्यान्वयन का उपयोग कर रहे हैं)।

वही तर्क अन्य (कभी-कभी उपयोगी विधियों) जैसे toString, hashCode आदि पर लागू होता है। दूसरी विधि इनके उपयोगी कार्यान्वयन प्रदान नहीं करती है।

+0

वास्तव में टाइप 1 (sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl) बराबर के कार्यान्वयन पैरामीटरेटेड टाइप के बराबर के पैरामीटर को कास्ट करने के लिए प्रतीत होता है और फिर कक्षाओं की तुलना करने के लिए इंटरफ़ेस विधियों का उपयोग करता है, इसलिए 'type1.equals (type2)' सत्य वापस आ जाएगा, हालांकि विपरीत ('type2.equals (type1)') झूठी वापसी करेगा; आप उन्हें भी लागू कर सकते हैं, लेकिन फिर कोड थोड़ा छोटा हो जाता है –

+0

निश्चित रूप से। विधि 1 में विधि 2 में आपको वही परिणाम मिल सकता है, लेकिन आपको कुछ और काम की आवश्यकता है, जैसा आपने देखा है। – aioobe

2

असल में, मुझे लगता है कि ऐसा करने का सबसे आसान तरीका (== कम से कम कोड) यह आपकी डमी इंटरफ़ेस होगा जिसमें आपकी रुचि है, और उसके बाद getGenericInterfaces()[0] अपनी कक्षा से (getGenericSuperclass() का उपयोग करें यदि आप कक्षा में रूचि रखते हैं) :

private interface MapStringString extends Map<String, String> {} 
private static ParameterizedType mapStringString(){ 
    return (ParameterizedType) MapStringString.class.getGenericInterfaces()[0]; 
} 

यह अच्छी तरह से बड़े पैमाने हालांकि, जैसा कि आप हर ParameterizedType प्रतिनिधित्व करने के लिए चाहते हैं के लिए एक नया वर्ग बनाने के लिए doen't। मैं नहीं देखता कि आपका कार्यान्वयन क्यों नहीं करेगा (जब तक कि वहां कहीं भी संकुचित न हो), और इसमें आकर्षक लाभ होता है जिसे आप इसे पुन: प्रयोज्य बना सकते हैं।

+0

हालांकि यह पहली विधि के रूप में 'हैकिश' जैसा प्रतीत होता है, यह कम से कम बेहतर दिखने वाला कोड देता है जहां आप प्रकार प्राप्त करने का प्रयास करते हैं (बस वर्ग प्राप्त करने के बजाय फ़ंक्शन को कॉल करना, फिर विधि प्राप्त करें, फिर प्रत्येक सामान्य जेनेरिक रिटर्न टाइप प्राप्त करें समय आप इसका उपयोग करना चाहते हैं)। –

5

यदि आप अपनी परियोजना में Google की Guava लाइब्रेरी शामिल करते हैं (आपको चाहिए; यह बहुत अच्छा है), एक प्रकार प्राप्त करने के लिए TypeToken का उपयोग करें। Google की Gson लाइब्रेरी (जेएसओएन के साथ बातचीत के लिए) के समान version है।

Type t = new TypeToken<List<String>>(){}.getType(); 

आप किसी भी तीसरे पक्ष के पुस्तकालयों पर भरोसा नहीं करना चाहते हैं, तो आप अभी भी गुमनाम प्रकार एक सामान्य ठोस साथ प्रकार प्राप्त करने के लिए उपयोग कर सकते हैं: दोनों एक TypeList<String> का प्रतिनिधित्व प्राप्त करने के लिए इस (तरह इस्तेमाल कर रहे हैं । कोड (इस तकनीक इंटरफेस के साथ काम नहीं करेंगे और अधिक परेशानी की तुलना में यह सार प्रकार के लिए लायक है हो सकता है) की एक पंक्ति प्राप्त करने के लिए TypeHashMap<String, String> को दिखाने वाला, ऐसा करते हैं:

Type t = new HashMap<String, String>(){}.getClass().getGenericSuperclass(); 

मैंजिसके परिणामस्वरूप कि सत्यापित किया है 0 उदाहरण .equals()TypeGson के TypeToken द्वारा बनाए गए उदाहरण, हालांकि Guava के TypeToken के संस्करण के लिए सत्यापित नहीं किया गया है, जिस पर मुझे इस समय तक पहुंच नहीं है।(अमरूद एक अधिक सामान्य उद्देश्य पुस्तकालय है जो सभी प्रकार की चीजों के लिए बहुत आसान है, आपको शायद इसका उपयोग करना चाहिए।)

+0

यह अभी भी आवश्यक है कि सूची संकलन समय पर ज्ञात है। ओपी में, कच्चे प्रकार और पैरामीटर प्रकार संकलित प्रकार तक नहीं जानते थे। – user48956

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