java - 访问父类(super class)的私有(private)字段

标签 java inheritance private inner-classes

众所周知,类之间不继承私有(private)字段。令我感兴趣的是它如何用于内部静态类。 考虑以下代码:

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
        }
    }
}

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

最佳答案

内部类是后来进入 Java 的入口。添加它们时,它们仅作为编译器扩展添加,对 JVM 没有任何更改。

语言规范声明内部类被允许访问它在其中声明的类的私有(private)成员;这包括其他内部类。

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

请注意增加了 access$200 和 access$300。它们分别提供对私有(private)方法和字段的后门访问。

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        
}

And if it is legal, why it is possible only via "super.XXX" construct?

私有(private)字段通常不是字段的编译器解析路径的一部分,通过强制开发人员指定 super,编译器确保私有(private)访问是本意而不是错误。

关于java - 访问父类(super class)的私有(private)字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25991377/

相关文章:

java - 如何在没有所有子节点文本的情况下获取直接元素的文本

python - 如何在抽象模型的 ManyToMany 字段中设置 related_name?

C++:从模板参数继承

java - 我怎样才能使 Java 方法对除测试之外的所有调用者都是私有(private)的?

c++ - 复制构造函数应该是私有(private)的还是公共(public)的

java - 根据数据库属性返回 getItemViewType

Java 泛型未经检查强制转换警告 : abstract class A<T extends A>

Java导入静态错误

c++ - 为什么 operator = 不从模板类继承

iphone - rippleEffect 是私有(private) Api 吗?操作系统