我在下面写的代码工作正常,但我对合成方法有疑问。生成这些是为了访问私有数据。但是我有成员类中使用的外部类的公共实例变量,所以为了访问实例变量,它创建了合成方法(因为它在类文件中! )。
代码段如下:
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);
}
}
}
类文件生成如下。 对于内部类A,作为TestInnerClass $ A:
import java.io.PrintStream;
class TestInnerClass$A {
TestInnerClass$A(TestInnerClass paramTestInnerClass) {
}
void display() {
System.out.println(this.this$0.x);
}
}
为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)。为什么显示方法在类文件中有不同的不同定义?
2)。为什么TestInnerClass类文件实例变量被访问为 TestInnerClass.this.x 。但是在TestInnerClass $ A的类文件中,相同的代码是不同的 this.this $ 0.x ??
3)为什么JVM创建合成方法为这个$ 0 ,但 实例变量是公共的 ??
答案 0 :(得分:3)
我不完全确定我理解你的问题,但我会尝试回答这些问题:
- 为什么显示方法在类文件中有不同的定义?
醇>
您无法将java文件与类文件进行比较。某些功能仅存在于一个世界中。内部类是一个这样的功能。他们没有直接翻译成字节码。有些代码按摩是必要的,这是你在这里发现的。
- 为什么
不同 醇>TestInnerClass
类文件实例变量被访问为TestInnerClass.this.x
。但是TestInnerClass$A
的类文件中的相同代码与this.this$0.x
??
因为在编译内部类时,对外部类(TestInnerClass.this
)的隐式引用将转换为显式引用。由于此引用不具有标识符this
,因此称为this$0
。
- 为什么JVM创建合成方法为
醇>this$0
,但实例变量是public ??
这不是一种方法,据我所知,它不公开。它是一个存储对封闭类对象的引用的字段。为了访问该对象的x
,需要它。
答案 1 :(得分:1)
您可以从外部类访问变量,因为它们位于内部类的闭包中。 Closures存在于Java中,但Java字节代码中不存在该概念。您看到的合成变量和访问器是使闭包在java字节代码中工作所需的修改的一部分。
完全披露:Java中的闭包实际上并不是闭包。实际闭包捕获创建函数的整个环境。在Java中,内部类总是可以访问外部类成员和创建它的方法的最终局部变量。但它无法访问非最终的局部变量,就像使用像JavaScript这样的语言一样。