项目作者: mtumilowicz

项目描述 :
Member inner class compilation description.
高级语言: Java
项目地址: git://github.com/mtumilowicz/java11-member-inner-class-compilation.git


Build Status

java11-member-inner-class-compilation

We will discuss how member inner classes are compiled.

Reference: https://www.amazon.com/Java-Language-Features-Modules-Expressions/dp/1484233476

preview

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>

decompiler configuration

  1. Inner classes are hidden by default in Intellij explorer.
  2. Configuration of javap decompiler is child’s play:
    1. ctrl + alt + s (Settings)
    2. external tools
    3. +(plus)
      • Program: $JDKPath$\bin\javap.exe
      • Arguments: -c $FileClass$
        • -c Prints out disassembled code
      • Working directory: $OutputPath$
  3. Using javap from context menu:
    • right click on the class -> External Tools -> javap
  4. Using javap from terminal:
    “java_home\bin\javap.exe” -c path_to_compiled\Outer$Inner.class

project description

  1. The easiest example, package: easy

    1. class Outer {
    2. class Inner {
    3. }
    4. }

    is compiled to two classes:

    • Outer$Inner.class

      1. class Outer$Inner {
      2. final Outer this$0;
      3. Outer$Inner(Outer outer) {
      4. this$0 = outer;
      5. super();
      6. }
      7. }
      • 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
    • Outer.class
      1. class Outer {
      2. Outer() {
      3. }
      4. }
      • the coupling between Outer and Inner is removed
        in the compilation
  2. Inner class has constructor, package: constructor

    1. class Outer {
    2. class Inner {
    3. Inner(String s) {
    4. }
    5. }
    6. }

    is compiled to two classes:

    • Outer$Inner

      1. class Outer$Inner {
      2. final Outer this$0;
      3. Outer$Inner(Outer outer, String s) {
      4. this$0 = outer;
      5. super();
      6. }
      7. }
      • additional param (Outer) was added to the existing constructor
    • Outer.class same as (1.)
  3. accessing private fields, package: accessing.priv

    1. class Outer {
    2. private String s = "outer";
    3. class Inner {
    4. String getS() {
    5. return s;
    6. }
    7. }
    8. }

    is compiled to two classes:

    • Outer.class

      1. class Outer {
      2. private String s = null;
      3. Outer() {
      4. s = "outer";
      5. }
      6. static String access$000(Outer outer) {
      7. return outer.s;
      8. }
      9. }
      • static method for extracting private field (flagged by
        compiler - we don’t have direct access)
    • Outer$Inner

      1. class Outer$Inner {
      2. final Outer this$0;
      3. Outer$Inner(Outer outer) {
      4. this$0 = outer;
      5. super();
      6. }
      7. String getS() {
      8. return Outer.access$000(this$0);
      9. }
      10. }
  4. accessing non-private fields, package: accessing.npriv

    1. class Outer {
    2. String s = "outer";
    3. class Inner {
    4. String getS() {
    5. return s;
    6. }
    7. }
    8. }

    is compiled to two classes:

    • Outer$Inner

      1. class Outer$Inner {
      2. final Outer this$0;
      3. Outer$Inner(Outer outer) {
      4. this$0 = outer;
      5. super();
      6. }
      7. String getS() {
      8. return this$0.s;
      9. }
      10. }
    • Outer.class

      1. class Outer {
      2. private String s = null;
      3. Outer() {
      4. s = "outer";
      5. }
      6. }
      • no static method this time