2011-03-28 11 views
8

मैं आज इस में भाग गया और केवल एक चीज जो मैं सोच सकता हूं वह यह है कि यह जावा कंपाइलर में एक बग है। निम्न कोड संकलित करता है, लेकिन निश्चित रूप से गलत लगता है (चूंकि testMethod में बच्चे में एक differenet हस्ताक्षर है लेकिन माता-पिता को ओवरराइड करता है) और रनटाइम पर क्लास कास्ट अपवाद फेंक देगा।जेनेरिक जोड़ना आपको एक अलग रिटर्न प्रकार के साथ एक विधि को ओवरराइड करने की अनुमति देता है?

public interface TestInterface<T> { 
    public List<String> testMethod(); // <-- List<String> 
} 
public class TestClass implements TestInterface { 
    @Override 
    public List<Integer> testMethod() { // <-- List<Integer> overriding List<String>!! 
     return Collections.singletonList(1); 
    } 
} 

और इसके बाद के संस्करण संरचना का उपयोग:

public void test() { 
    TestInterface<Boolean> test = new TestClass(); 
    List<String> strings = test.testMethod(); 
    for (String s : strings) { 
    System.out.println(s); 
    } 
} 

यह सब ठीक संकलित, लेकिन अगर आप इसे चलाने के स्पष्ट रूप से वर्ग डाली अपवाद फेंक देते हैं।

आप TestInterface से <T> हटाने, या लाइन TestClass implements TestInterface<T> तो कोड अब संकलन होगा, जो समझ में आता है में में T भरें। इमो <T>testMethod के संकलन पर कोई असर नहीं होना चाहिए क्योंकि यह उस विधि में कोई भूमिका नहीं निभाता है। शायद टेस्टइंटरफेस में <T> जोड़ना संकलक को विधि हस्ताक्षर टाइप करने का कारण बन रहा है भले ही T उन विधियों में भाग नहीं लेता है ...?

क्या किसी को पता है कि यहां क्या हो रहा है?

+0

+1। सामान्य कार्यान्वयन –

उत्तर

9

यदि आप कच्चे प्रकार के रूप में एक सामान्य वर्ग को तत्काल बनाते हैं, सभी इसमें जेनेरिक जेनरेट पैरामीटर संकलक द्वारा छोड़े जा रहे हैं, इसलिए यह आपको संकलन के दौरान कोई चेतावनी/त्रुटियां नहीं देता है। अर्थात। घोषित

public class TestClass implements TestInterface ... 

प्रभावी रूप से

public interface TestInterface { 
    public List testMethod(); 
} 
public class TestClass implements TestInterface { 
    @Override 
    public List testMethod() { 
     return Collections.singletonList(1); 
    } 
} 

जो वास्तव में ठीक संकलित में कोड गिरावट होती है।

इसी तरह की समस्या कुछ हफ्ते पहले पोस्ट की गई थी, the answer to which यह बताते हुए कि यह एक कंपाइलर बग नहीं है, बल्कि पिछड़े संगतता के लिए एक जानबूझकर डिजाइन निर्णय है।

+0

में कुछ वास्तव में, वास्तव में अजीब गेटचा होना चाहिए, अच्छी तरह से कहा गया है, "मिटाएं" कुंजी शब्द है। Google इसे और आप देखेंगे कि उपरोक्त कोड से बाहर आने वाले बिट-कोड में कोई सबूत नहीं है कि जेनरिक का भी उपयोग किया गया था। – somid3

0

जिस तरह से मैं समझता हूं कि जेनिक्स एक कंपाइलर साइड चीज है। सामान्य फ़ाइल प्रकार के बारे में कुछ भी नहीं, क्लास फ़ाइल में शामिल है, यह एक कंपाइलर हैक की तरह है। यही कारण है कि आप जेनेरिक-मुक्त कक्षाओं के साथ जेनेरिक-लड़े कॉलों को आसानी से जोड़ सकते हैं और रनटाइम पर कोई समस्या नहीं है। मैंने सुना है कि सभी डॉटनेट सामग्री जेनेरिक-प्रकार की जानकारी ऑब्जेक्ट फ़ाइल के भीतर प्रथम श्रेणी के नागरिक बनाती हैं।

तो वैसे भी, ये लोग स्पष्ट रूप से आपकी समस्या को बेहतर तरीके से जानते हैं, लेकिन आपको वास्तव में संकलन करने वाले सभी चीज़ों पर विचार करना चाहिए।

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

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