Java通过受保护的getter访问私有超类成员

Posted

技术标签:

【中文标题】Java通过受保护的getter访问私有超类成员【英文标题】:Java accessing private superclass member through protected getter 【发布时间】:2016-05-22 19:27:47 【问题描述】:

我知道在 Java 中,只要超类提供公共或受保护的 getter 方法,您就可以在子类中访问超类的私有成员。然而,我也知道子类实际上并没有继承私有成员。考虑以下情况....

Class A 
    private var = 2;
    protected int getVar()
        return var;
    


Class B extends A

   public void printVar()
       System.out.println(getVar());
   


Class Main

    public static void main(args [])

         B b= new B();
         b.printVar();
    

我想了解,既然我们正在创建子类 B 的实例,那么该私有成员究竟是什么时候以及何时分配给内存的,它的范围是什么?既然 A 的实例实际上从未被创建,它是如何存在的?它不是静态变量,也不是最终变量,所以它是动态堆栈还是隐式堆动态?我认为,当您从超类实例化子类时,您也会继承非私有的成员和方法,然后将这些成员实例化为子类的对象实例的一部分(除非它们被覆盖等),所以只有一个对象被分配为堆动态变量。但是,如果这些私有成员没有被继承,那么编译器是否只是为它们提供堆栈动态引用以防调用继承的 getter 方法并且仅在这种情况下?

【问题讨论】:

【参考方案1】:

不过我也知道子类实际上并没有继承私有成员。

是的。 B 的实例A 的实例,它包含所有相同的字段。您无法再直接访问私有字段,但它们仍然存在。

由于实际上从未创建过 A 的实例,它是如何存在的?

当您创建B 时,A 中的构造函数也会被调用,以确保将B 实例正确初始化为有效的A。不要将子类视为与超类不同的东西。 B 仍然是 A;它只是做得更多。

【讨论】:

【参考方案2】:

您认为超类的私有成员不被子类继承的假设是错误的。所有成员都是继承的。子类的私有成员是子类实例的一部分,但不能通过子类的代码直接访问。

在返回私有成员的值的超类中有一个受保护的 getter 为子类提供了一种访问私有成员值的方法(尽管它不能修改它,除非你也有一个受保护的或超类中的公共二传手)。

【讨论】:

尽管根据 JLS .... .还是我误解了这个? (docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.2):声明为私有的类的成员不会被该类的子类继承。只有声明为受保护或公共的类的成员才能被声明在包中的子类继承,而不是在其中声明该类的那个。 啊,没关系,仔细看后,我不明白它在说什么。 @LorenShqipognja 我想这是一个解释问题。通过“不继承”,JLS 意味着子类不能访问私有成员。它们仍然由超类的代码分配和初始化。 就我的问题而言,但是您的解释是正确的,谢谢:) 您好 Eran,我认为您的回答中有一个小错字。 “子类的私有成员是子类实例的一部分”应该是“超类的私有成员是子类实例的一部分”

以上是关于Java通过受保护的getter访问私有超类成员的主要内容,如果未能解决你的问题,请参考以下文章

继承 Java 私有成员

Java中的间接子类无法访问的超类中的受保护成员

向某些类公开受保护/私有属性

[在C ++中没有getter setter的访问成员

PHP访问控制

访问受保护或私有财产