繁体   English   中英

访问超类的私有字段

[英]Access to private field of a super class

众所周知,私有字段不会在类之间继承。 令我着迷的是它如何用于内部静态类。 考虑以下代码:

public class Main {
    public static void main(String[] args) {
        new B();
    }

    private static class A {
        private int a = 10;

        private void foo() {
            System.out.println("A.foo");
        }
    }

    private static class B extends A {
        {
            // foo();    // compile-time error
            super.foo();    // ok

            // System.out.println(a);    // compile-time error
            System.out.println(super.a);    // ok
        }
    }
}

您能否解释一下如何访问其他内部类的私有字段? 如果合法,为什么只能通过“ super.XXX”构造实现?

内部类是Java的较晚入门。 添加它们时,它们仅作为编译器扩展添加,对JVM不变。

语言规范指出,内部类被允许访问在其内声明的类的私有成员。 包括其他内部类。

为了使其工作,编译器会生成桥接方法。 上面示例中的javap与Main $ A一起使用看起来像这样:

注意access $ 200和access $ 300的添加。 它们分别提供对私有方法和字段的后门访问。

class Main$A {
  Main$A(Main$1);
    Code:
       0: aload_0       
       1: invokespecial #3                  // Method "<init>":()V
       4: return        

  static void access$200(Main$A);
    Code:
       0: aload_0       
       1: invokespecial #2                  // Method foo:()V
       4: return        

  static int access$300(Main$A);
    Code:
       0: aload_0       
       1: getfield      #1                  // Field a:I
       4: ireturn       
}

为了完整起见,这是Main $ B的生成代码。 注意对access $ 200和300的调用,它们出现在Java代码中super.a和super.foo()的位置。

class Main$B extends Main$A {
  public Main$B();
    Code:
       0: aload_0       
       1: aconst_null   
       2: invokespecial #1                  // Method Main$A."<init>":(LMain$1;)V
       5: aload_0       
       6: invokestatic  #2                  // Method Main$A.access$100:(LMain$A;)V
       9: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      12: aload_0       
      13: invokestatic  #4                  // Method Main$A.access$200:(LMain$A;)I
      16: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
      19: return        
}

如果合法,为什么只能通过“ super.XXX”构造实现?

专用字段通常不属于编译器用于字段的解析路径的一部分,通过强制开发人员指定超级字段,编译器可以确定专用访问是什么意思,而不是错误。

JLS3 6.6.1 :“私有类成员或构造函数只能在顶级类(第7.6节)的主体内进行访问,该顶级类将成员或构造函数的声明括起来。它不能被子类继承。

由于内部类可在顶级类的主体内访问,因此其可访问类和子类不在封闭类之内。 现在规范没有说明应该如何发生-这实际上不是规范的工作。 实现它确实取决于实现程序员,而这些细节未在当前规范中记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM