We will discuss how member inner classes are compiled.
Reference: https://www.amazon.com/Java-Language-Features-Modules-Expressions/dp/1484233476
A member inner class is defined inside a class the same way a member field or a member method. It could be private, package-level, protected, public.
Naming convention: <outer-class-name>$<member-inner-class-name>
- Inner classes are hidden by default in Intellij explorer.
- Configuration of javap decompiler is child's play:
- ctrl + alt + s (Settings)
- external tools
+
(plus)- Program:
$JDKPath$\bin\javap.exe
- Arguments:
-c $FileClass$
-c
Prints out disassembled code
- Working directory:
$OutputPath$
- Program:
- Using javap from context menu:
- right click on the class -> External Tools -> javap
- Using javap from terminal: "java_home\bin\javap.exe" -c path_to_compiled\Outer$Inner.class
- The easiest example, package:
easy
is compiled to two classes:class Outer { class Inner { } }
Outer$Inner.class
class Outer$Inner { final Outer this$0; Outer$Inner(Outer outer) { this$0 = outer; super(); } }
- final field for
Outer
instance was added - note that
super()
is after setting the field - a one-param constructor that accepts
Outer
is inserted during compilation
- final field for
Outer.class
class Outer { Outer() { } }
- the coupling between
Outer
andInner
is removed in the compilation
- the coupling between
- Inner class has constructor, package:
constructor
is compiled to two classes:class Outer { class Inner { Inner(String s) { } } }
Outer$Inner
class Outer$Inner { final Outer this$0; Outer$Inner(Outer outer, String s) { this$0 = outer; super(); } }
- additional param (
Outer
) was added to the existing constructor
- additional param (
Outer.class
same as(1.)
- accessing private fields, package:
accessing.priv
is compiled to two classes:class Outer { private String s = "outer"; class Inner { String getS() { return s; } } }
Outer.class
class Outer { private String s = null; Outer() { s = "outer"; } static String access$000(Outer outer) { return outer.s; } }
- static method for extracting private field (flagged by compiler - we don't have direct access)
Outer$Inner
class Outer$Inner { final Outer this$0; Outer$Inner(Outer outer) { this$0 = outer; super(); } String getS() { return Outer.access$000(this$0); } }
- accessing non-private fields, package:
accessing.npriv
is compiled to two classes:class Outer { String s = "outer"; class Inner { String getS() { return s; } } }
Outer$Inner
class Outer$Inner { final Outer this$0; Outer$Inner(Outer outer) { this$0 = outer; super(); } String getS() { return this$0.s; } }
Outer.class
class Outer { private String s = null; Outer() { s = "outer"; } }
- no static method this time