Java vs. Groovy inner / outer class mismatch

Java:

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"); } } 

Output at startup:

 inner outer 

Groovy:

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

Output at startup:

 $ 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) 

Why is this a mismatch? Using Outer.outer() works, however, in any way, avoid typing the class name?

+6
source share
2 answers

You can add import static Outer.outer to the top of the script to avoid typing the class name (kinda) ... at least you don't enter it inside the method.

In addition to the explanation already provided, if you check the AST browser in the Groovy console at the "Exit" stage, you will see that both classes are upper levels, so "Internal" cannot allow external methods without import.

 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 { } 
+4
source

Groovy's default behavior is dynamic: it resolves the link at run time, not compile time. In Java, the compiler recognizes that the call to outer() is static and actually resolves to its parent class. In the byte code, you will find a fully qualified reference to the called static method. (The parent class in this case.) Groovy, on the other hand, resolves the call at runtime (unless you use the @CompileStatic annotation), and therefore the bytecode generated by the Groovy compiler will not have a fully qualified link, so Groovy will not will know that the method is found only in the parent class, it will just try to resolve it in the inner class, which will fail.

Minor inconsistency: Groovy methods return Object , and Java methods return void . This is not necessarily a big deal, but it will create compatibility issues if your Java code calls Groovy objects and you make changes.

+3
source

Source: https://habr.com/ru/post/977493/


All Articles