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?
Method Local inner classes can't use a local variable of the outer method until that local variable is not declared as final.
An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance. To instantiate an inner class, you must first instantiate the outer class.
1) First and most important difference between Inner class and nested static class is that Inner class require instance of outer class for initialization and they are always associated with instance of enclosing class. On the other hand nested static class is not associated with any instance of enclosing class.
A static class is a class that is created inside a class, is called a static nested class in Java. It cannot access non-static data members and methods. It can be accessed by outer class name.
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 {
}
Groovy's default behavior is dynamic: it resolves the reference at runtime, not compile time. In Java, the compiler recognizes the call to outer()
is static and actually resolves it to the parent class. In the bytecode, you will find a fully-qualified reference to the static method being invoked. (The parent class in this case.) Groovy, by contrast, resolves the call at runtime (unless you use the @CompileStatic
annotation) and so the bytecode generated by the Groovy compiler will not have a fully-qualified reference. Therefore, at runtime, Groovy will not know that the method is found only in the parent class, it will simply try to resolve it in the inner class, which will fail.
Minor discrepancy: your Groovy methods are returning Object
, while the Java methods are void
. This isn't necessarily a big deal, but it will create compatibility problems if your Java code is calling Groovy objects and you make changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With