我知道所有局部变量都将存储在堆栈内存中,而对象和静态变量将存储在堆中。但是当我遇到以下让我感到困惑的代码时。
public class Outer {
private int a =10;
public void outerMethod() {
int x = 30;
class Inner {
private int b = 20;
public void innerMethod() {
System.out.println("The Value of a is: "+a);
System.out.println("The Value of b is: "+b);
System.out.println("The Value of x is: "+x);
}
};
Inner inner = new Inner();
inner.innerMethod();
}
}
上面的代码运行良好。但我的问题是x 是outerMethod() 的局部变量。当我们创建一个 Outer 类的对象,并在其上调用 outerMethod() 时,x 将存储在堆栈框架中,我还定义了一个内部类的类定义并创建了对象它,然后我在它上面调用 innerMethod() 。
所以Inner Class的对象必须存储在堆中。如果是这样,那么它如何访问 x??
最佳答案
Inner
只能访问 x
如果 x
是最终的(或者,来自 Java 8 effectively final )。在幕后,编译器会注意到 Inner
对象使用了哪些外部变量,并将它们传递给 Inner
构造函数(这些将是合成构造函数参数 - 由编译器,所以你不会看到它们)。然后它们将成为 Inner
类的最终(同样,合成 = 生成并向您隐藏)字段。当您在 Inner
类代码中引用 x
时,编译器会将其替换为对 中合成
类。x
字段的引用复制值的内部
您可以使用这个有用的命令查看更多详细信息:
javac -d . -XD-printflat MyFile.java
会生成对应实际字节码的Java代码:
class Outer {
/*synthetic*/ static int access$000(Outer x0) {
return x0.a;
}
Outer() {
super();
}
private int a = 10;
public void outerMethod() {
int x = 30;
/*synthetic*/ {
}
;
Outer$1Inner inner = new Outer$1Inner(this, x);
inner.innerMethod();
}
}
class Outer$1Inner {
/*synthetic*/ final Outer this$0;
/*synthetic*/ final int val$x;
Outer$1Inner(final Outer this$0, /*synthetic*/ final int val$x) {
// Notice the synthetic references to the surrounding Outer object
// and to the x local variable
// Both become fields of Inner
this.this$0 = this$0;
this.val$x = val$x;
super();
}
private int b = 20;
public void innerMethod() {
System.out.println("The Value of a is: " + Outer.access$000(this$0));
System.out.println("The Value of b is: " + b);
System.out.println("The Value of x is: " + val$x);
}
}
您还可以注意到 Outer.a
是如何被访问的——因为 Inner
被编译成一个“普通的旧 Java 类”,它必须遵守可见性修饰符,所以JVM 不允许直接访问私有(private)字段 Outer.a
。但是,在编译过程中,编译器会注意到你要从Inner
访问这个字段,因为它是一个内部类,所以会生成一个访问器方法Outer.access$000()
。由于 Inner
引用了 Outer
对象,它可以调用 Outer.access$000(referenceToOuter)
并获取 Outer 的值.a
.
关于java - 方法中的类如何访问该方法的局部变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33718123/