谁能解释这段与 Java 中的阴影相关的代码?

Can anyone explain this code related to shadowing in Java?

在阅读有关嵌套的 Oracle 文档时 类,我发现这段代码的输出我无法理解。有人可以解释一下吗?

public class ShadowTest {

    public int x = 0;

    class FirstLevel {

        public int x = 1;

        void methodInFirstLevel(int x) {
            System.out.println("x = " + x);
            System.out.println("this.x = " + this.x);
            System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
        }
    }

    public static void main(String... args) {
        ShadowTest st = new ShadowTest();
        ShadowTest.FirstLevel fl = st.new FirstLevel();
        fl.methodInFirstLevel(23);
    }
}

下面是这个例子的输出:

x = 23
this.x = 1
ShadowTest.this.x = 0 //why is 0 printed here? why not 1 because "this" is the object of FirstLevel class.

可以找到原代码here

局部变量x隐藏了this.xShadowTest.this.x

内部class(this.x)的实例变量隐藏了封闭class(可以被ShadowTest.this.x访问)的实例变量。

System.out.println("x = " + x); // prints the local variable passed to the method
System.out.println("this.x = " + this.x); // prints the instance variable of the inner class
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x); // prints the instance variable of the enclosing class instance

我觉得除了找到的文档之外还没有完全解释 here 所以我将根据我最近的理解尝试更详细地解释。

我已将 ShadowClass 外部 class 的名称更改为 NestedClasses 并将变量从类型 int 更改为类型 String

这是在第一个嵌套 class 中添加第二个嵌套 class 的示例,以显示 NestedClasses.this.x 如何继续在 classes 的更深层表现。

public class NestedClasses {
    
    public String x = "outer class variable";
    
    class FirstLevel {

        public String x = "first level class variable";

        void methodInFirstLevel(String x) {
            System.out.println("methodInFirstLevel:");
            System.out.println("x = " + x);
            System.out.println("this.x = " + this.x);
            System.out.println("NestedClasses.this.x = " + NestedClasses.this.x);
        }
        
        class SecondLevel {
            
            public String x = "second level class variable";

            void methodInSecondLevel(String x) {
                System.out.println("methodInSecondLevel:");
                System.out.println("x = " + x);
                System.out.println("this.x = " + this.x);
                System.out.println("NestedClasses.this.x = " + NestedClasses.this.x);
                System.out.println("FirstLevel.this.x = " + FirstLevel.this.x);
                System.out.println("NestedClasses.FirstLevel.this.x = " + NestedClasses.FirstLevel.this.x);
            }
        }
    }

    public static void main(String[] args) {

        NestedClasses st = new NestedClasses();
        NestedClasses.FirstLevel fl = st.new FirstLevel();
        NestedClasses.FirstLevel.SecondLevel sl = fl.new SecondLevel();

        fl.methodInFirstLevel("first level method arg");
        System.out.println();
        sl.methodInSecondLevel("second level method arg");
    }
}

输出:

methodInFirstLevel:
x = 第一级方法 arg
this.x = 第一级 class 变量
NestedClasses.this.x = 外部 class 变量

SecondLevel 方法:
x = 二级方法 arg
this.x=二级class变量
NestedClasses.this.x = 外部 class 变量
FirstLevel.this.x=一级class变量
NestedClasses.FirstLevel.this.x=一级class变量

三个实例化对象(stflsl)中的每一个都包含指向不同内存的指针space 在可以找到 x 的值的堆中。我相信编译器正在向最外层“向后”搜索以找到第一个匹配的 class,当它看到嵌套 class 中的 class 名称前缀为 this 时。它找到的第一个匹配 class 是它在确定需要搜索哪个对象实例以找到 x 时将引用的 class。这意味着 NestedClasses.FirstLevel.this.x 实际上是向后退两步,向前退一步以确定在堆中查看哪个 内存 space,即哪个内存 space x 参考.

夏天:
NestedClasses.this.x

  • 带前缀的 Class 名称 NestedClasses 告诉 JVM 正在使用哪个 class,这个 class 必须可以从当前范围访问。
  • this 关键字告诉 JVM 查看 内存 space 被引用的 class 的实例化对象,而不是 class 对象本身的 内存 space(用于 class 的静态成员)。更具体地说,this 将引用用于(和需要)实例化非静态内部 class.
  • 的外部 class 的实例化
  • 附加到 this 的对象成员 x 告诉 JVM 在它正在查看的 内存 space 中搜索什么。