这是 程序员指南Java™SCJP认证综合入门书 - 第三版 - Khalid A. Mughal Rolf W. Rasmussen 的一个例子,我不能理解。
我知道如果我们没有将其继承到另一个包中定义的子类,我们就无法访问受保护的成员。
但我仍然无法理解为什么我们无法从子类的子类中访问它。
示例如下
package packageA;
public class A {
protected int z;
}
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?????
}
}
答案 0 :(得分:3)
目前接受的答案没有回答这个问题。它解释了为什么您无法从z
或A
的正文中访问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
的类型为C
,C
是B
的子类。< / p>
但在C
内你不能说obj2.z
,因为obj2
的类型为B
而B
不是的子类C
。
总结受保护的含义:
假设在类A
的主体内声明受保护的成员。
(1)您可以从包含A
。
(2)此外,在不同包中定义的S
的子类A
可以访问S
实例上的受保护成员或继承自{{ 1}},但不是S
继承的类的实例。
最后一句是回答这个问题的关键点。
答案 1 :(得分:1)
受保护的成员可以仅由类的子类访问,其中相同包中的或类被声明为受保护的类会员被宣布。在你的情况下,类B和C在不同的包中声明为类A的。这就是为什么你不能通过对类A的引用访问'z'。如果你将类B和C移动到与A相同的包中,它将工作。
这就是为什么你不能在C类中访问obj2.z,因为'z'是在不同包中的类中声明的。