2013-08-27 9 views
48

समस्या का सारांश: मैं (जैसे ArrayList<SomeClass> के रूप में उदाहरण के लिए) एक प्रकार पैरामीटर के साथ एक कक्षा पास करने के लिए चाहते हैं एक प्रकार पैरामीटर के रूप में एक सामान्य विधि के लिए ।एक वर्ग जावा में सामान्य विधि के लिए प्रकार पैरामीटर के रूप में प्रकार पैरामीटर के साथ पासिंग

चलो कहते हैं कि मैं एक विधि है दो:

public static <T> T getGenericObjectFromJson(String json, Class<T> genericType){ 
     // details unimportant, basically returns an object of specified type 
     return JsonParser.fromJson(json, genericType); 
    } 

इस विधि, ज़ाहिर है, वर्ग के किसी भी प्रकार के लिए बिल्कुल ठीक काम करेंगे। मैं उदाहरण के लिए, तो जैसे विधि कॉल कर सकते हैं:

getGenericObjectFromJson(jsonString, User.class) 

समस्या: मुझे लगता है मैं ऐसा नहीं कर सकते पता चला:

getGenericObjectFromJson(jsonString, ArrayList<User>.class) 

वाक्य रचना, इस स्पष्ट रूप से अवैध है। हालांकि, मुझे यकीन नहीं है कि मैं इस तरह कुछ कैसे पूरा करूंगा। मैं, निश्चित रूप से, ArrayList.class पास कर सकता हूं, हालांकि सामान्य प्रकार के अतिरिक्त इसे अब वाक्य रचनात्मक रूप से वैध नहीं बनाता है, और मैं इसके चारों ओर एक तरीके से नहीं सोच सकता।

केवल प्रत्यक्ष समाधान कुछ इस तरह (जो बल्कि नासमझ लगती है) कर दिया गया है:

getGenericObjectFromJson(jsonString, new ArrayList<User>().getClass()) 

लेकिन हम अंत में सामान्य प्रकार वैसे भी खोने, और केवल वापस (हालांकि यह कर सकते हैं अज्ञात प्रकार की एक ArrayList मिल कास्ट किया जा सकता है)। इसके अलावा, अनावश्यक रूप से किसी ऑब्जेक्ट को तुरंत चालू करना।

मेरे एकमात्र समाधान अब तक एक वर्ग है कि एक सामान्य प्रकार पैरामीटर जो, instantiated जा सकता है ताकि तरह होता है में है कि विधि रैप करने के लिए कर दिया गया है:

public class JsonDeserializer<T>... 

इस मामले में, getGenericObjectFromJson विधि वर्ग के उपयोग करेगा सामान्य प्रकार

प्रश्न (ओं): आखिरकार, मैं उत्सुक हूं कि मैं एक प्रकार के पैरामीटर के साथ कक्षा क्यों नहीं पारित कर सकता हूं, और क्या मैंने जो करने का प्रयास किया है उसे पूरा करने का कोई तरीका है या नहीं।

हमेशा के रूप में, मुझे इस प्रश्न के साथ कोई समस्या होने पर बताएं।

+7

मिटाए जाने के कारण, मुझे नहीं लगता कि यह संभव है। जावा जेनेरिक एक संकलन-समय का निर्माण होता है और रनटाइम पर मौजूद नहीं होता है, इसलिए ऐसी कोई चीज नहीं है जो 'क्लास' ऑब्जेक्ट को निर्मित जेनेरिक प्रकार का प्रतिनिधित्व करती है। – cdhowie

+3

समाधान: 'सी #', न सिर्फ मजाक कर रहा है। आप "टाइप एरर" के कारण ऐसा नहीं कर सकते हैं, जेनेरिक टाइप जानकारी –

+1

को हटाकर जब आप संकलित करते हैं तो जावा क्या करता है, क्या यह इसे 'getGenericArrayListFromJson (jsonString, User.class)' के रूप में पुन: संपादित करने के लिए काम करेगा? यह शायद सबसे अच्छा है जिसे आप करने में सक्षम होने जा रहे हैं। –

उत्तर

55

यह कुछ "चाल" का उपयोग करके जावा में वास्तव में संभव है। सी # fanatics से दबाव के लिए झुकाओ मत! (J/k)

"चाल" एक वर्ग है कि एक सामान्य प्रकार फैली बनाते हैं, और Type.getGenericSuperclass() या .getGenericInterfaces() द्वारा लौटाए के माध्यम से माता पिता वर्ग के प्रकार के पैरामीटर का मान तक पहुँचने के लिए है।

यह काफी बोझिल है। हमारे जीवन को सरल बनाने के लिए, Google ने हमारे लिए कोड के अधिकांश उबाऊ हिस्से को पहले से ही लिखा है, और इसे अमरूद के माध्यम से उपलब्ध कराया है।

TypeToken कक्षा की जांच करें, जो वास्तव में आप चाहते हैं। उदाहरण के लिए:

TypeToken<List<String>> stringListTok = new TypeToken<List<String>>() {}; 

तो फिर तुम एक Class<T> के बजाय एक TypeToken<T> चारों ओर गुजरती हैं और इतना ही है। यह आपको टी द्वारा प्रतिनिधित्व किए गए प्रकार पर प्रतिबिंब करने के तरीकों के साथ प्रदान करता है।

क्या यह आंतरिक रूप से कर रही है बस .getClass().getGenericSuperclass() (या ...Interfaces()) बुला रहा है, तो Type से ParameterizedType करने के लिए और (आदि .getActualTypeArguments(),) वहाँ से सभी जानकारी को पुन: प्राप्त कुछ बदसूरत डाले।

अंत में, यदि आप निर्भरता इंजेक्शन के साथ कुछ ऐसा करना चाहते हैं (यानी, मान लीजिए कि आपको कक्षा के निर्माता पर Class<T> इंजेक्ट करने की आवश्यकता है, या आप कुछ पैरामीटरयुक्त इंटरफ़ेस का उदाहरण प्राप्त करना चाहते हैं, जिसमें उदाहरण होना चाहिए टाइप पैरामीटर पर निर्भर करता है), Google Guice (Google से एक डी कंटेनर) में TypeLiteral नामक समस्या को हल करने के लिए एक बहुत ही समान तंत्र है। दृश्यों के पीछे उपयोग और कोड लगभग TypeToken गुवा से समान है। इसे यहां देखें: TypeLiteral

+1

वाह, यह वास्तव में कमाल है। बहुत मजेदार बात, मैं वास्तव में Google जीसन की लाइब्रेरी का उपयोग कर रहा हूं, जो गुवा के (या कम से कम भागों) का उपयोग करता है, हालांकि मुझे स्पष्ट रूप से समझ में नहीं आया कि टाइपटोकन कैसे काम करता है। बहुत बहुत उपयोगी जानकारी, बहुत उपयोगी जानकारी। –

+0

क्या कोई पहले तरीके से अधिक विस्तृत कर सकता है। AFAIK, आप जावा में एक सामान्य प्रकार का विस्तार नहीं कर सकते हैं। – Kedarnath

+0

@ केदारनाथ, 'कक्षा ए {} कक्षा बी एक {} '-> यह बिल्कुल ठीक है। क्या यह वही है जिसके बारे में आप बात कर रहे है? क्या आप एक उदाहरण प्रदान करने में सक्षम होंगे कि आप क्या संभव नहीं होने का दावा करते हैं? –

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

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