In the following code snippet, presumably it appears that it should issue some compilation error but it doesn't:
class Outer {
public static class Inner {
static String obj = "Inner";
}
static Optional Inner = new Optional();
//The (inner) class name and the object name are same.
}
class Optional {
String obj = "Optional";
}
public class Main {
public static void main(String[] args) {
System.out.println(Outer.Inner.obj);
//Refers to the string inside the optional class
}
}
The class Outer
has a static class inside it named Inner
. Additionally, it declares an object (static) of the class Optional
(static Optional Inner = new Optional();
)
This object and the class names (inside the class Outer
) are same which is Inner
. The program displays Optional
. The only expression Outer.Inner.obj
within main()
is expected to display Inner
but it doesn't. The actual output is however Optional
which is the case of the Optional
class.
One way to display Inner
is by changing the object name to something else.
static Optional Inner1 = new Optional();
From the output it displays, it appears that the object name (or a variable) is chosen over a type name (the class Inner
) because they have the same name. What exact case is applied here?
Actually the class name is Outer$Inner.
Inner classes are essentially a hack introduced in Java 1.1. The JVM doesn't actually have any concept of an inner class, and so the compiler has to bodge it. The compiler generates class
B
"outside" of classA
, but in the same package, and then adds synthetic accessors/constructors to it to allowA
to get access to it.Checkout the following post:
Java inner class visibility puzzle
Paragraph 6.4.2 of the Java Language Specification has some information about the rules that apply in this case.
This refers to paragraph 6.5 Determining the Meaning of a Name, which explains the rules in detail.
In your example,
Outer.Inner
could refer to the type of the nested class namedInner
, or the static member variableInner
. The rules say the variable will be chosen over the type.Think of the inner class has actually have its own .java file. That will make it clear to you why it chooses the variable over the Inner class.