无法访问子类中受保护的成员,该子类也是子类

时间:2011-07-29 20:49:15

标签: java oop scope

这是 程序员指南Java™SCJP认证综合入门书 - 第三版 - Khalid A. Mughal Rolf W. Rasmussen 的一个例子,我不能理解。

我知道如果我们没有将其继承到另一个包中定义的子类,我们就无法访问受保护的成员。

但我仍然无法理解为什么我们无法从子类的子类中访问它。

示例如下

A.java

package packageA;
public class A {
    protected int z;
}

B.java

package packageB;

import packageA.A;

public class B extends A {

    void action(A obj1, B obj2, C obj3) {
        z = 10;      // z in B - Works
        obj1.z = 10; // Won't work for obvious reason
        obj2.z = 10; // z in B - Works
        obj3.z = 10; // z in C - Works

    }
}

class C extends B {

    void action(A obj1, B obj2) {
        z = 10; // Works
        obj1.z = 10; // Won't work for obvious reason
        obj2.z = 10; // z in B - WHY DOESN'T THIS WORK?????

    }
}

2 个答案:

答案 0 :(得分:3)

目前接受的答案没有回答这个问题。它解释了为什么您无法从zA的正文中访问B实例的成员C。但问题是,您无法从z内访问B个实例的成员C

原因是B不是C的子类。阅读Java规范,第6.6.2.1节:

  

设C是声明受保护成员的类。只允许在C的子类S的主体内访问。

     

此外,如果Id表示实例字段或实例方法,则:

     

如果访问是通过限定名称Q.Id ,其中Q是ExpressionName,则当且仅当表达式Q的类型为S或a时,才允许访问S的子类。

     

http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2.1   

(bolding mine)

因此,在B中,您可以说obj3.z,因为obj3的类型为CCB的子类。< / p>

但在C内你不能说obj2.z,因为obj2的类型为BB 不是的子类C


总结受保护的含义:

假设在类A的主体内声明受保护的成员。

(1)您可以从包含A

的包中的任何位置访问受保护的成员

(2)此外,在不同包中定义的S的子类A可以访问S实例上的受保护成员或继承自{{ 1}},但不是S继承的类的实例。

最后一句是回答这个问题的关键点。

答案 1 :(得分:1)

受保护的成员可以由类的子类访问,其中相同包中的类被声明为受保护的类会员被宣布。在你的情况下,类B和C在不同的包中声明为类A的。这就是为什么你不能通过对类A的引用访问'z'。如果你将类B和C移动到与A相同的包中,它将工作。

这就是为什么你不能在C类中访问obj2.z,因为'z'是在不同包中的类中声明的。