69. Java 嵌套类 - 变量遮蔽现象

238 阅读2分钟

69. Java 嵌套类 - 变量遮蔽现象

阴影(Shadowing)现象

在 Java 中,“阴影”或“遮蔽”现象指的是当在嵌套作用域中使用相同名称的变量时,内层作用域中声明的变量会隐藏外层作用域中同名的变量。这意味着在内层作用域中直接使用该名称时,总是引用离当前作用域最近的变量。如果需要访问被内层变量遮蔽的外层变量,则必须使用限定名称。


1. 何为“阴影”?
  • 示例说明: 假设在外部类中声明了变量 x,而在内部类或方法参数中又声明了同名变量 x,此时内层的 x 会覆盖外层的 x。例如:

    public class ShadowTest {
        public int x = 0;  // 外层变量
    
        class FirstLevel {
            public int x = 1;  // 内层变量
    
            void methodInFirstLevel(int x) {  // 方法参数,也命名为 x
                System.out.println("x = " + x);                   // 输出方法参数 x
                System.out.println("this.x = " + this.x);         // 输出 FirstLevel 的 x
                System.out.println("ShadowTest.this.x = " + ShadowTest.this.x); // 输出外部类的 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
    
    • x = 23:方法参数 x 遮蔽了其他同名变量;
    • this.x = 1this.x 指向当前 FirstLevel 内部类的成员;
    • ShadowTest.this.x = 0:通过限定名称访问外部类 ShadowTestx 字段。

2. 如何访问被隐藏的变量

在出现变量遮蔽时,可通过以下方式访问各层次的变量:

  1. 直接使用变量名
    • 在当前作用域内,如果有同名变量,则直接引用该变量。例如在 methodInFirstLevel 中直接写 x 就指向方法参数。
  2. 使用 this.x
    • 在内部类中,this.x 指向当前对象的字段。如果内部类有自己的字段 x,则 this.x 访问的是内部类的 x
  3. 使用 OuterClassName.this.x
    • 在内部类中,如果需要访问外部类的同名变量,可以使用限定名称,例如 ShadowTest.this.x 来明确指定外部类的 x

3. 为什么会出现阴影现象
  • 作用域规则: Java 编译器在遇到同名变量时,会优先查找当前作用域内的变量。这种“就近原则”会导致内层声明的变量自动遮蔽外层的变量。
  • 设计初衷: 允许在不同作用域中使用同一名称,可以在局部上下文中突出参数与局部变量的含义,但同时要求开发者在需要访问外层变量时使用限定名称以消除歧义。

4. 小结
  • 阴影/遮蔽: 当内层作用域中声明的变量与外层同名时,内层变量将遮蔽外层变量,使得直接引用只得到内层变量。
  • 访问外层变量: 使用 this.x 可访问内部类自身的字段,使用 OuterClass.this.x 则能访问外层类的变量。
  • 命名注意: 为了提高代码可读性,通常应避免出现过多同名变量,但在必要时,通过限定名称来消除歧义是 Java 的标准做法。