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

2 回答 2

4

您可以import static Outer.outer在脚本顶部添加一个以避免输入类名(有点)......您至少避免在方法中输入它。

为了补充已经提供的解释,如果您在输出阶段检查 Groovy 控制台中的 AST 浏览器,您可以看到这两个类都是顶级的,因此“内部”在没有导入的情况下无法解析为外部的方法。

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 { 

}
于 2014-10-30T20:45:19.803 回答
3

Groovy 的默认行为是动态的:它在运行时而不是编译时解析引用。在 Java 中,编译器识别出调用outer()是静态的,并实际将其解析为父类。在字节码中,您将找到对正在调用的静态方法的完全限定引用。(本例中的父类。)相比之下,Groovy 在运行时解析调用(除非您使用@CompileStatic注解),因此 Groovy 编译器生成的字节码将没有完全限定的引用。因此,在运行时,Groovy 不会知道该方法仅在父类中找到,它会简单地尝试在内部类中解析它,这会失败。

小差异:您的 Groovy 方法返回Object,而 Java 方法返回void. 这不一定是什么大问题,但是如果您的 Java 代码正在调用 Groovy 对象并且您进行了更改,则会产生兼容性问题。

于 2014-10-30T20:37:03.853 回答