2014-10-30 64 views
6

爪哇:運行時爪哇與Groovy的內/外類出入

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

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

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

輸出::運行時

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 

Groovy的

$ 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

您可以在腳本的頂部添加一個import static Outer.outer以避免輸入類名(有點)...您至少要避免在方法中鍵入它。

爲了補充已經提供的解釋,如果您在Output階段檢查Groovy Console中的AST瀏覽器,可以看到這兩個類都是頂級的,所以「Inner」無法解析爲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

謝謝! :(<---我的悲傷的臉 – 2014-10-30 21:01:44

3

Groovy的默認行爲是動態的:它在運行時解析引用,而不是編譯時。在Java中,編譯器識別對outer()的調用是靜態的,實際上將其解析爲父類。在字節碼中,您將找到對正在調用的靜態方法的完全限定引用。 (在這種情況下,父類)。相比之下,Groovy在運行時解析調用(除非使用@CompileStatic註釋),因此Groovy編譯器生成的字節碼將不具有完全限定的引用。因此,在運行時,Groovy不會知道該方法僅在父類中找到,它只會嘗試在內部類中解析它,否則將會失敗。

細微差異:您的Groovy方法返回Object,而Java方法爲void。這不一定是個大問題,但如果您的Java代碼正在調用Groovy對象並進行更改,則會產生兼容性問題。