2

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

代码片段如下:

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创建合成方法this$0,但是实例变量是公共的

4

2 回答 2

3

不完全确定我是否理解您的问题,但我会尝试回答:

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

您不能将 java 文件与此类文件进行比较。有些功能只存在于一个世界中。内部类就是这样一个特性。他们没有直接翻译成字节码。一些代码按摩是必要的,这就是您在这里发现的。

  1. 为什么在TestInnerClass类文件中实例变量被访问为TestInnerClass.this.x. 但是相同的代码在 as 的类文件中是不同TestInnerClass$Athis.this$0.x??

因为在编译内部类时,对外部类 ( TestInnerClass.this) 的隐式引用被转换为显式引用。由于这个引用不能有标识符this,所以它被称为this$0

  1. 为什么JVM创建了合成方法this$0,但是实例变量是公共的?

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

于 2015-01-22T14:04:07.310 回答
1

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

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

于 2015-01-22T14:23:25.820 回答