Search code examples
javagroovygroovyshell

Java vs. Groovy inner / outer class discrepancy


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 when run:

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 when run:

$ 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 this discrepancy? Using Outer.outer() works, however any way to avoid typing the class name?


Solution

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

    To complement the already-provided explanation, if you inspect the AST Browser inside Groovy Console at the Output stage, you can see that both classes are top-level, so "Inner" can't resolve to Outer's methods without the 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 { 
    
    }