2014-10-30 13 views
6

जावा:जावा बनाम ग्रूवी आंतरिक/बाहरी वर्ग विसंगति

public final class Outer { 
    public static void main(String[] args) { 
     Inner.inner(); 
    } 

    private static final class Inner { 
     private static void inner() { 
     System.out.println("inner"); 
     outer(); 
     } 
    } 

    private static void outer() { 
     System.out.println("outer"); 
    } 
} 

आउटपुट जब चलाएँ:

inner 
outer 

ग्रूवी:

public final class Outer { 
    static main(String[] args) { 
    Inner.inner() 
    } 

    static outer() { 
    println('outer') 
    } 

    static final class Inner { 
    static inner() { 
     println('inner') 
     outer() 
    } 
    } 
} 

आउटपुट जब चलाएँ:

$ groovy Outer 
inner 
Caught: groovy.lang.MissingMethodException: No signature of method: static Outer$Inner.outer() is applicable for argument types:() values: [] 
Possible solutions: inner(), use([Ljava.lang.Object;), use(java.lang.Class, groovy.lang.Closure), use(java.util.List, groovy.lang.Closure), putAt(java.lang.String, java.lang.Object), grep() 
groovy.lang.MissingMethodException: No signature of method: static Outer$Inner.outer() is applicable for argument types:() values: [] 
Possible solutions: inner(), use([Ljava.lang.Object;), use(java.lang.Class, groovy.lang.Closure), use(java.util.List, groovy.lang.Closure), putAt(java.lang.String, java.lang.Object), grep() 
     at Outer$Inner.inner(Outer.groovy:13) 
     at Outer$Inner$inner.call(Unknown Source) 
     at Outer.main(Outer.groovy:3) 

यह विसंगति क्यों? Outer.outer() का उपयोग करना, हालांकि कक्षा का नाम टाइप करने से बचने का कोई तरीका है?

उत्तर

4

कक्षा नाम (kinda) टाइप करने से बचने के लिए आप स्क्रिप्ट के शीर्ष पर import static Outer.outer जोड़ सकते हैं ... आप कम से कम विधि के अंदर टाइपिंग से बचें।

पहले से प्रदत्त स्पष्टीकरण के पूरक के लिए, यदि आप आउटपुट चरण में ग्रोवी कंसोल के अंदर एएसटी ब्राउज़र का निरीक्षण करते हैं, तो आप देख सकते हैं कि दोनों कक्षाएं शीर्ष-स्तर हैं, इसलिए "आंतरिक" बिना बाहरी के तरीकों को हल नहीं कर सकता आयात।

final public class Outer implements groovy.lang.GroovyObject extends java.lang. Object { 

} 
final public static class Outer$Inner implements groovy.lang.GroovyObject extends java.lang.Object { 

} 
+0

धन्यवाद! :(<--- मेरा दुखद चेहरा –

3

ग्रोवी का डिफ़ॉल्ट व्यवहार गतिशील है: यह रनटाइम पर संदर्भ को हल करता है, समय संकलित नहीं करता है। जावा में, संकलक outer() पर कॉल को पहचानता है स्थिर है और वास्तव में इसे मूल वर्ग में हल करता है। बाइटकोड में, आपको आवंटित स्थैतिक विधि के लिए एक पूर्ण-योग्य संदर्भ मिलेगा। (इस मामले में अभिभावक वर्ग।) ग्रोवी, इसके विपरीत, रनटाइम पर कॉल को हल करता है (जब तक आप @CompileStatic एनोटेशन का उपयोग नहीं करते) और इसलिए ग्रोवी कंपाइलर द्वारा उत्पन्न बाइटकोड में पूर्णतः योग्यता प्राप्त संदर्भ नहीं होगा। इसलिए, रनटाइम पर, ग्रोवी को यह नहीं पता होगा कि विधि केवल मूल वर्ग में पाई जाती है, यह केवल आंतरिक कक्षा में इसे हल करने का प्रयास करेगी, जो असफल हो जाएगी।

मामूली विसंगति: आपकी ग्रोवी विधियां Object लौट रही हैं, जबकि जावा विधियां void हैं। यह जरूरी नहीं है कि यह एक बड़ा सौदा है, लेकिन यदि आपका जावा कोड ग्रोवी ऑब्जेक्ट्स को कॉल कर रहा है और आप बदलाव करते हैं तो यह संगतता समस्याएं पैदा करेगा।

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