进入超级班级的私人领域 [英] Access to private field of a super class

查看:87
本文介绍了进入超级班级的私人领域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As everyone knows, private fields are not inherited between classes. What intrigues me, is how it works for inner static classes. Consider the following code:

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"构造来实现?

Can you please explain how it is possible to access private fields of other inner class? And if it is legal, why it is possible only via "super.XXX" construct?

推荐答案

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

Inner classes were a late entry to Java. When they were added they were added as a compiler extension only, no change to the JVM.

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

The language spec stated that an inner class was allowed to access the private members of the class that it was declared within; that includes other inner classes.

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

To make it work, the compiler generates bridge methods. Using javap with Main$A from the example above looks like this:

请注意,要另外添加access $ 200和access $ 300.它们分别提供对私有方法和字段的后门访问.

Notice the addition of access$200 and access$300. They provide back door access to the private method and field respectively.

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()的位置.

For completeness, here is the generated code for Main$B. Notice the calls to access$200 and 300, they appear where super.a and super.foo() appeared in the Java code.

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"构造来实现?

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

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

private fields are not usually part of the compilers resolution path for fields, by forcing developers to specify super the compiler is making certain that private access is what was meant and not a mistake.

这篇关于进入超级班级的私人领域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆