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

时间:2015-01-22 13:55:45

标签: java inner-classes .class-file java-synthetic-methods

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

代码段如下:

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 ,但 实例变量是公共的 ??

2 个答案:

答案 0 :(得分:3)

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

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

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

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

因为在编译内部类时,对外部类(TestInnerClass.this)的隐式引用将转换为显式引用。由于此引用不具有标识符this,因此称为this$0

  
      
  1. 为什么JVM创建合成方法为this$0,但实例变量是public ??
  2.   

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

答案 1 :(得分:1)

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

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