【问题标题】:Can anyone explain this code related to shadowing in Java?谁能解释这段与Java中的阴影相关的代码?
【发布时间】:2015-11-11 08:51:43
【问题描述】:

在阅读有关嵌套类的 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找到

【问题讨论】:

  • 你到底有什么不明白的?请解释更多。
  • 有什么问题 - 你不明白所有的输出,只有一个?
  • this 前加上一个封闭类的名称,例如ShadowTest.this.x,会导致它引用封闭的对象。
  • ShadowTest.this.x 的输出我没看懂。
  • @RishabhGour - 查看将使用的field 取决于调用它的引用。 ShadowTest.this.x 表示访问ShadowTest's x

标签: java shadowing


【解决方案1】:

局部变量x阴影this.xShadowTest.this.x

内部类的实例变量(this.x)隐藏了封闭类的实例变量(可以通过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

【讨论】:

  • 先生,ShadowTest.this 究竟是什么意思?在我的理解中,这应该是指FirstLevel 类和ShadowTest 的对象。这应该意味着访问ShadowTest,"this" 的成员。
  • @RishabhGour ShadowTest.this 指的是您的内部类实例的封闭实例(即与调用该方法的FirstLevel 实例相关联的ShadowTest 实例)。
  • 因此,如果假设在 A 类中的 B 类中有一个 C 类,那么我可以通过说 A.this 从 C 类中引用 A 类对象,同样适用于 B 类,对吗?
【解决方案2】:

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

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

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

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 = 第一级方法参数
this.x = 第一级类变量
NestedClasses.this.x = 外部类变量

methodInSecondLevel:
x = 二级方法参数
this.x = 二级类变量
NestedClasses.this.x = 外部类变量
FirstLevel.this.x = 一级类变量
NestedClasses.FirstLevel.this.x = 一级类变量

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

夏天:
NestedClasses.this.x

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-22
    • 2011-02-11
    • 1970-01-01
    • 2014-09-16
    • 2021-04-24
    相关资源
    最近更新 更多