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 ??
不完全确定我理解你的问题,但我会尝试回答它们:
- why the display method is having different definition in class files?
您不能像这样比较 java 文件和 class 文件。某些功能仅存在于一个世界中。内部 classes 就是这样一个功能。他们没有直接翻译成字节码。一些代码按摩是必要的,这是你在这里发现的。
- 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=]
.
- 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.
这样的语言那样访问非最终局部变量。
我在下面编写了运行良好的代码,但我对 合成方法 有一个疑问。因为这些是为了访问私有数据而生成的。但我有 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 ??
不完全确定我理解你的问题,但我会尝试回答它们:
- why the display method is having different definition in class files?
您不能像这样比较 java 文件和 class 文件。某些功能仅存在于一个世界中。内部 classes 就是这样一个功能。他们没有直接翻译成字节码。一些代码按摩是必要的,这是你在这里发现的。
- why in
TestInnerClass
class file instance variable is accessed asTestInnerClass.this.x
. but the same code is different in class file ofTestInnerClass$A
asthis.this[=13=].x
??
因为在编译内部class时,对外部class(TestInnerClass.this
)的隐式引用被转换为显式引用。由于此引用不能具有标识符 this
,因此称为 this[=16=]
.
- 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.
这样的语言那样访问非最终局部变量。