Member Class(Inner class) 如何访问外部 class 的实例变量?

How Member Class(Inner class) is accessing instance variable of outer class?

我在下面编写了运行良好的代码,但我对 合成方法 有一个疑问。因为这些是为了访问私有数据而生成的。但我有 public 外部 class 的实例变量 在成员 class 中使用,因此为了访问它创建的实例变量 合成方法(因为它在class文件中!!)。

代码片段如下:

public class TestInnerClass {
    public int x = 10;
        public static void main(String[] args) {
            TestInnerClass test= new TestInnerClass();
            A obj = test.new A();
            obj.display();
        }

        class A {
            void display() {
            System.out.println(x);
        }
    }
}

class 文件生成如下。 对于内部 class A 作为 TestInnerClass$A:

import java.io.PrintStream;

class TestInnerClass$A {
    TestInnerClass$A(TestInnerClass paramTestInnerClass) {
    }

    void display() {
        System.out.println(this.this[=14=].x);
    }
}

class 为 TestInnerClass 生成文件:

import java.io.PrintStream;
public class TestInnerClass {
    public int x = 10;
    public static void main(String[] args) { 
        TestInnerClass test = new TestInnerClass();
        TestInnerClass tmp13_12 = test; tmp13_12.getClass(); A obj = new A();
        obj.display();
   } 

   class A {
       A() {
       }
       void display() {
           System.out.println(TestInnerClass.this.x);
       }
   }
}

所以我的疑问是:

1).为什么显示方法在 class 个文件中有不同的定义??

2).为什么在 TestInnerClass class 文件实例变量中访问为 TestInnerClass.this.x。但相同的代码在 TestInnerClass$A 的 class 文件中与 this.this$0.x??

不同

3) 为什么 JVM 创建合成方法为 this$0,然而 实例变量是 public ??

不完全确定我理解你的问题,但我会尝试回答它们:

  1. why the display method is having different definition in class files?

您不能像这样比较 java 文件和 class 文件。某些功能仅存在于一个世界中。内部 classes 就是这样一个功能。他们没有直接翻译成字节码。一些代码按摩是必要的,这是你在这里发现的。

  1. why in TestInnerClass class file instance variable is accessed as TestInnerClass.this.x. but the same code is different in class file of TestInnerClass$A as this.this[=13=].x??

因为在编译内部class时,对外部class(TestInnerClass.this)的隐式引用被转换为显式引用。由于此引用不能具有标识符 this,因此称为 this[=16=].

  1. why JVM created synthetic method as this[=16=], however instance variable is public??

这不是一种方法,据我所知,它不是 public。这是一个存储对封闭 class 对象的引用的字段。需要它才能访问该对象的 x

您可以从外部 class 访问变量,因为它们位于内部 class 的闭包中。 Closures 存在于 Java 但该概念不存在于 Java 字节码中。您看到的合成变量和访问器是使闭包在 java 字节代码中工作所需的一部分。

完全披露:Java 中的闭包实际上并不是闭包。实际的闭包捕获创建函数的整个环境。在 Java 中,内部 class 始终可以访问外部 class 成员和创建它的方法的最终局部变量。但是,它不能像 JavaScript.

这样的语言那样访问非最终局部变量。