2010-09-10 14 views
10

संभव डुप्लिकेट:
Get generic type of java.util.Listजावा में मानचित्र के मूल्य प्रकार कैसे प्राप्त करें?

मैं एक नक्शा है और मुझे लगता है कि मानचित्र का एक उदाहरण से टी के प्रकार प्राप्त करना चाहते हैं। मैं उसे कैसे कर सकता हूँ?

उदा।

Map<String, Double> map = new HashMap<String, Double>(); 
... 
String vtype = map.getValueType().getClass().getName(); //I want to get Double here 

बेशक वहाँ एपीआई में ऐसी कोई 'getValueType()' समारोह है: मैं की तरह कुछ करना चाहते हैं।

+4

इसे देखें: http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list –

+0

आप [प्रतिबिंब] (http://download.oracle.com/javase का उपयोग कर सकते हैं /tutorial/reflect/index.html) – Aillyn

+0

कार्यात्मक आवश्यकता क्या है? प्रतिबिंब के साथ झुकाव से बेहतर समाधान हो सकते हैं। – BalusC

उत्तर

8

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

इसे टाइप एरर के रूप में जाना जाता है।

import java.lang.reflect.*; 
import java.util.*; 

public class Generic { 
    private Map<String, Number> map = new HashMap<String, Number>(); 

    public static void main(String[] args) { 
     try { 
      ParameterizedType pt = (ParameterizedType)Generic.class.getDeclaredField("map").getGenericType(); 
      for(Type type : pt.getActualTypeArguments()) { 
       System.out.println(type.toString()); 
      } 
     } catch(NoSuchFieldException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

ऊपर कोड प्रिंट होगा: एक और अधिक औपचारिक परिभाषा में JLS.

+2

यह सटीक नहीं है; ऐसा करने के लिए आवश्यक सटीक कोड देने के उत्तर दिए गए हैं, –

+2

वास्तव में यह इस विशेष मामले के लिए 100% सही है: यदि आपके पास सब कुछ कहा गया है, तो खोजने के लिए कोई प्रकार की जानकारी नहीं है, कुछ भी नहीं। प्रश्न में नक्शा हैश मैप प्रकार है, क्योंकि यहां पैरामीटर पैरामीटर संकलन के बाद छोड़ दिए जाते हैं (वे बाइट कोड में जरूरी प्रकार के प्रकार को प्रेरित करते हैं)। – StaxMan

12

हैं अपने Map है एक घोषित क्षेत्र, आप निम्न कर सकते प्रदान की जाती है

class java.lang.String 
class java.lang.Number 

हालांकि, यदि आपके पास बस Map का उदाहरण है, उदाहरण के लिए अगर यह एक विधि के लिए पारित किए गए, तो आप जानकारी उस समय नहीं मिल सकता है:

public static void getType(Map<String, Number> erased) { 
    // cannot get the generic type information directly off the "erased" parameter here 
} 

आप विधि हस्ताक्षर (फिर से ऊपर मेरे उदाहरण की तरह प्रतिबिंब का उपयोग कर,) erased के प्रकार का निर्धारण करने के लिए हड़पने सकता है, लेकिन यह वास्तव में आपको कहीं भी नहीं मिलता है (नीचे संपादित देखें)।

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

BalusC के नीचे टिप्पणी ध्यान दिया जाना चाहिए। आपको वास्तव में ऐसा करने की आवश्यकता नहीं है; आप पहले से ही मानचित्र के प्रकार की घोषणा की है, इसलिए आपको पहले से कहीं ज्यादा जानकारी नहीं मिल रही है। उसका answer here देखें।

+0

प्रतिबिंब का उपयोग मानचित्र में संदर्भित मानों पर रनटाइम पर किया जा सकता है। –

+4

नोट किया जाना चाहिए कि यह केवल ** घोषित ** जेनेरिक प्रकार (जैसे 'मानचित्र <स्ट्रिंग, इंटेगर> मैप' भाग में) लौटाता है, ** ** तत्काल ** सामान्य प्रकार (जैसा कि 'नया हैशैप <स्ट्रिंग, इंटीजर' >() 'भाग)। जैसा कि मेरे उत्तर में लिंक किए गए डुप्लिकेट में इंगित किया गया है; अगर आप उन्हें कोड में ही घोषित कर चुके हैं तो उन्हें इस तरह से ढूंढने का कोई मतलब नहीं है ... – BalusC

+0

@ बालुससी - सहमत; डिजाइन विकल्पों के बारे में सवाल पर आपकी टिप्पणी शायद इस सवाल को लेने के लिए बेहतर दिशा है। मेरे उत्तर में कोड ओपी को संकलन-समय पर पहले से ही जानता है उससे अधिक जानकारी देता है। –

1

हालांकि सही उत्तरों दिए गए हैं, एक और विकल्प है जिसे अभी तक इंगित नहीं किया गया है। असल में फ़ील्ड और विधियां एकमात्र ऐसी जगह नहीं हैं जहां सामान्य प्रकार की जानकारी रह सकती है: सुपर-क्लास घोषणा में यह जानकारी भी है।

इसका मतलब यह है कि यदि आपके मानचित्र वास्तव में एक उप-प्रकार की तरह है:

class MyStringMap extends HashMap<String,String> { } 

तो यह instance.getClass पर 'getGenericSuperclass' (फोन करके सामान्य प्रकार पैरामीटर है कि इस्तेमाल किया गया, यह पता लगाने के लिए संभव है() '), और उसके बाद आवंटित वास्तविक प्रकार पैरामीटर तक पहुंच। यह काफी शामिल हो जाता है क्योंकि पैरामीटर को पदानुक्रम को पार करना होता है ताकि यह सुनिश्चित किया जा सके कि मापदंडों को मानचित्र से ठीक से बाध्य किया जा सके (एलियाज्ड आदि हो सकता है), लेकिन यह किया जा सकता है।और इस तरह से "सुपर टोकन" है की तरह सामान्य घोषणा पारित करने के लिए प्रयोग किया जाता है:

new TypeToken<Map<String, Double>>() { } 

जो कई जावा चौखटे (जर्सी, Guice, जैक्सन और कई और अधिक)

समस्या यहाँ से प्रयोग किया जाता है, हालांकि वह यह है कि यह एक उदाहरण के नाममात्र प्रकारों को निर्धारित करने की अनुमति देता है, यह केवल सामान्य काम के वास्तविक गैर-जेनेरिक उप-वर्ग होने पर ही काम करता है, और मुझे इस आवश्यकता को लागू करने के तरीके के बारे में पता नहीं है (कॉलिंग कोड को यह अजीब लगता है कि यह आवश्यक है इस उद्देश्य के लिए बस कुछ हद तक फर्जी मानचित्र उप-वर्ग बनाएं)।

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