2017-02-26 13 views
8

जबकि investigating a stack trace discrepancy एक और जवाब लिखते समय, मैं एक ऐसे व्यवहार में आया जो मुझे समझ में नहीं आया। निम्नलिखित परीक्षण कार्यक्रम पर विचार करें (यह जहाँ तक नीचे मैं इसे संकीर्ण सकता है के रूप में है):स्टैक ट्रेस में रहस्यमय रेखा

interface TestInterface <U> { 
    void test (U u); 
} 

static class Test <T extends Test<T>> implements TestInterface<T> { // line 11 
    @Override public void test (T t) { 
     throw new RuntimeException("My exception"); // line 13 
    } 
} 

static class TestA extends Test<TestA> { } 
static class TestB extends Test<TestB> { } 

public static void main (String[] args) throws Exception { 

    try { 
     Test a = new TestA(); 
     Test b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

    try { 
     TestInterface a = new TestA(); 
     Test b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

    try { 
     TestInterface a = new TestA(); 
     TestInterface b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

} 

लाइन्स 11 और 13 से ऊपर स्निपेट में दर्शाये जाते हैं और यह run on ideone हो सकता है। उस कार्यक्रम का उत्पादन होता है:

java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone.main(Main.java:25) 
java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone$Test.test(Main.java:11) 
    at Ideone.main(Main.java:33) 
java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone$Test.test(Main.java:11) 
    at Ideone.main(Main.java:41) 

मेरा प्रश्न है: क्यों दूसरे और तीसरे टेस्ट केस के लिए स्टैक ट्रेस में लाइन 11 है? तीन परीक्षण मामलों के बीच अंतर a और b के घोषित प्रकार हैं।

लाइन 11 (वर्ग घोषणा लाइन) निम्नलिखित परिस्थितियों में ही मौजूद है: Test एक अंतरफलक को लागू करता है

  1. हैं, और
  2. अपवाद इंटरफ़ेस विधि से फेंक दिया जाता है, तो और
  3. यदि इंटरफ़ेस एक प्रकार पैरामीटर लेता है, और
  4. यदि कक्षा घोषणा के प्रकार पैरामीटर में extends Test<T> है (लाइन 11 को शामिल नहीं किया गया है तो इसे class Test<T> के रूप में घोषित किया गया है), और
  5. यदि विधि पर Test प्रकार के बजाय टाइप की जाती है।

कि ध्यान देने योग्य बात:

  • यह निश्चित रूप से मेरी अपवाद उत्पन्न किया जा रहा है (संदेश और स्टैक ट्रेस)।
  • अगर मैं अपना फेंक नहीं देता तो कोई अन्य अपवाद नहीं फेंक दिया जाता है।
  • मैंने इसे ओरेकल जेडीके 1.7, और 1.8 पर विंडोज पर और 1.8 विचार पर पुन: उत्पन्न किया है। हालांकि, 1.7 में 11 के बजाय लाइन 1 पर एक स्टैक ट्रेस तत्व शामिल है (जो दोगुना अजीब है)।

यहां क्या हो रहा है? उस रेखा को स्टैक ट्रेस में कैसे समाप्त किया जा रहा है और यह क्यों नहीं दिखता है कि दोनों ऑब्जेक्ट्स Test के रूप में घोषित किए गए हैं?

Here is the original program that prompted this, जहां java.lang.Enum की लाइन 55 वर्तमान अगर aComparable के रूप में घोषित किया जाता है लेकिन जब यह Enum के रूप में घोषित किया जाता है मौजूद नहीं है। लाइन 55 जेडीके स्रोत में Enum की घोषणा है, लाइन 180 स्पष्ट रूप से ClassCastException फेंक दिया गया है।

उत्तर

13

आप bridge method के प्रभावों को देख रहे हैं!

test विधि TestInterface में घोषित विलोपन test(Object) है, लेकिन test विधि Test में घोषित विलोपन test(Test) है। test(Object) विधि के लिए एक विधि खोज test(Test) विधि नहीं मिलेगी, इसलिए जावा वास्तव में Test के बाइटकोड में अलग test(Object) और test(Test) विधियों को अलग रखता है।

आपका पहला परीक्षण test(Test) विधि का उपयोग करता है, जो आपको अपेक्षित व्यवहार करता है। आपके अन्य परीक्षण test(Object) विधि का उपयोग करते हैं, जो सिंथेटिक ब्रिज विधि है जो केवल test(Test) विधि को कॉल करता है। इस पुल विधि में वास्तव में एक लाइन नंबर नहीं है, इसलिए यह 11 के

की काफी मनमानी रेखा संख्या के साथ स्टैक ट्रेस में दिखाई देता है।
संबंधित मुद्दे