2011-06-09 15 views
11

संभव डुप्लिकेट:
Why are not all type information erased in Java at runtime?रनटाइम पर पैरामिट्रीकृत प्रकार जानकारी तक पहुँचने

जावा के जेनरिक प्रकार विलोपन के माध्यम से लागू किया जाता है, तो मैंने सोचा कि यह पैरामिट्रीकृत प्रकार के बारे में कोई भी जानकारी प्राप्त करने के लिए कोई संभव हो गया था चलने के समय पर। हालांकि, मुझे जैक्सन पुस्तकालय में निम्नलिखित श्रेणी मिली।

void testTypeReference() { 
    // notice that we're instantiating an anonymous subclass of TypeReference 
    TypeReference<CurrencyDto> tr = new TypeReference<CurrencyDto>() {}; 
    assert tr.getType() == CurrencyDto.class 
} 

इस वर्ग दिखाता है:

(मैं इस उदाहरण के लिए वर्ग थोड़ा सरल बना दिया है)

public abstract class TypeReference<T> { 
    final Type _type; 

    protected TypeReference() { 
     Type superClass = getClass().getGenericSuperclass(); 
     _type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; 
    } 

    public Type getType() { return _type; } 

} 

वर्ग उस तक पहुँच पैरामिट्रीकृत प्रकार है के रूप में निम्नलिखित परीक्षण दर्शाता है प्रदान करता है वास्तविक प्रकार पैरामीटर रनटाइम (प्रतिबिंब का उपयोग करके) पर पुनर्प्राप्त किए जा सकते हैं, यह इस धारणा के अनुरूप कैसे है कि जावा जेनरिक टाइप प्रकार के माध्यम से लागू किए गए हैं?

+2

मुझे नहीं लगता कि यह उस अन्य प्रश्न का डुप्लिकेट है। वह प्रश्न पूछता है _why_ संकलक उस जानकारी को संग्रहीत करता है, जहां यह इस प्रकार के स्पष्टीकरण के लिए पूछता है कि यह प्रकार के मिटावट की धारणा के साथ कैसे फिट बैठता है। – ColinD

उत्तर

0

मुझे यहां कोई वास्तविक विरोधाभास नहीं दिख रहा है।

टाइपरेंसेंस को लीगेसी कोड के लिए रनटाइम पर कच्चे टाइप रेफरेंस प्रकार के रूप में माना जाएगा, लेकिन इसमें अभी भी कुछ प्रकार के बारे में जानकारी प्रदान करने की क्षमता है। किस प्रकार का मिटाने का मतलब यह है कि आप रनटाइम पर टी टाइप टाइपरेंस का उपयोग examplified here के रूप में नहीं कर सकते हैं। लेकिन आप अभी भी जान सकते हैं कि टी को प्रतिस्थापित किया गया है ..

4

यह वास्तव में काफी सरल है: आपको मूल्य INSTANCES से सामान्य जानकारी नहीं मिल सकती है, लेकिन आप इसे कुछ प्रतिबंधों के साथ TYPES (कक्षाओं) से प्राप्त कर सकते हैं। विशेष रूप से, ऐसे 3 स्थान हैं जहां सामान्य प्रकार की जानकारी उपलब्ध है (विवरण के लिए http://www.cowtowncoder.com/blog/archives/2008/12/entry_126.html देखें); सुपर-क्लास/इंटरफ़ेस घोषणा (सुपर प्रकार का पैरामीटरेशन), फील्ड घोषणाओं पर, और विधि (तर्क, वापसी प्रकार) घोषणाओं पर।

टाइप रेफरेंस के मामले में क्या होता है यह है कि आप निर्दिष्ट सुपर प्रकार के साथ एक अनाम प्रकार बनाते हैं; और तब यह जानकारी तब उपलब्ध होगी जब उस अनाम प्रकार (कक्षा) को पारित किया जाता है।

+0

"वास्तव में काफी सरल" - मैं आपसे असहमत हूं। –

+0

हे। खैर, यह विचार कि VALUE में सामान्य प्रकार की जानकारी नहीं है, लेकिन कक्षा परिभाषाएं सरल होती हैं। पूरी तरह से जेनेरिक नहीं, कि मैं दावा नहीं करता। :) लेकिन एफडब्ल्यूआईडब्ल्यू, यह (http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html) यह समझने में सक्षम हो सकता है कि यह सब कैसे काम करता है। – StaxMan

+0

@StaxMan, उत्तर और दिलचस्प लिंक के लिए धन्यवाद। –

12

कंक्रीट टाइप तर्क जानकारी क्लास फ़ाइलों में संग्रहीत होती है जब यह संकलन समय पर ज्ञात होती है। उदाहरण के लिए, यदि आपके पास ऐसी विधि वाला क्लास है जो List<String> (List<T> नहीं!) देता है तो वह जानकारी रनटाइम पर उपलब्ध होगी। इसी प्रकार, यदि आप एक वर्ग है:

public class Foo extends Bar<String> { 
} 

प्रकार तर्क String संकलन समय पर Foo करने में hardcoded है। TypeReference वर्ग (और गिस में TypeLiteral जैसे गिस में TypeLiteral और सभी समान संरचनाएं, इस कोड का उपयोग आपके कोड में अज्ञात उपclass बनाने के लिए आवश्यक है। जब आप ऐसा करते हैं, तो उस जानकारी के साथ एक वास्तविक वर्ग फ़ाइल उत्पन्न की जाएगी, जैसा ऊपर Foo उदाहरण के साथ है।

अधिक जानकारी के लिए, नील Gafter के ब्लॉग पोस्ट here देखें।

प्रकार विलोपन अधिक तथ्य यह है कि आप वास्तविक प्रकार तर्क के बारे में जानकारी रनटाइम पर एक सामान्य प्रकार का एक उदाहरण के लिए नहीं मिल सकता है को संदर्भित करता है (ध्यान दें कि Foo, Bar<String> का एक उपवर्ग, कोई प्रकार चर है और साधारण नहीं है)।

List<String> foo = new ArrayList<String>(); 

कोई प्रकार की जानकारी है कि वस्तु में संग्रहीत है: उदाहरण के लिए, यदि आप सामान्य प्रकार ArrayList<E> का एक उदाहरण बना सकते हैं। तो जब आप इसे किसी अन्य विधि के पास:

public <T> T foo(List<T> list) 

पता लगाने के लिए क्या T है कोई रास्ता नहीं है।

+0

यह कहना सही नहीं होगा कि "सूची खाली है, तो टी क्या है, यह जानने का कोई तरीका नहीं है?" मुझे थोड़ा मोटा लगता है लेकिन मैं वास्तव में अपने सिर में इसे मेल नहीं कर सकता हूं कि अगर जानकारी foo.get (0) .getClass() कर रही है तो सूची रन-टाइम पर उपलब्ध नहीं है। हालांकि मुझे एहसास है कि हमें टी को प्राप्त नहीं करना है क्योंकि सूची में ऑब्जेक्ट्स टी –

+0

@ मर्कस जूनियस ब्रूटस के उप-वर्ग हो सकते हैं: 'टी' जरूरी नहीं है कि पहले तत्व का प्रकार हो। उदाहरण के लिए, पहला तत्व 'डबल' हो सकता है जबकि 'टी'' संख्या' या 'ऑब्जेक्ट' है। साथ ही, ध्यान रखें कि प्रत्येक सामान्य वर्ग 'सूची' या कुछ अन्य कंटेनर नहीं है जहां आप विधि को कॉल करके 'टी' का उदाहरण प्राप्त कर सकते हैं। उदाहरण के लिए, 'तुलनात्मक', केवल एक विधि है जिसके लिए आप 'टी' के उदाहरण पास करते हैं। – ColinD

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