我有一个奇怪的错误,涉及保护修饰符。
我有以下代码:
package p1;
public class C1 {
protected void doIt() {}
}
package p2;
public class C2 extends p1.C1 {
private C1 c1_instance;
public void doItAgain() {
c1_instance.doIt(); // wtf!!!!
}
}
我收到错误,指出doIt()
已保护访问权限且无法访问!但我在子类中并且拥有并访问doIt()
方法。
这不是一个错误吗?
答案 0 :(得分:4)
我的印象是protected
意味着“可以从同一个包或子类访问”,但Java Language Specification当然更精确,并解释在C的子类S中,如果访问是通过限定名称Q.Id,其中Q是ExpressionName,则当且仅当表达式Q的类型是S或S的子类时才允许访问。“
因此,您只能通过对要调用的子类的引用来访问超类的protected
方法,如下所示:
public class C2 extends C1 {
private C2 c2_other_instance;
public void doItAgain() {
c2_other_instance.doIt();
}
}
如果您解释为什么要从子类的不同实例访问超类的一个实例,那么有人可能会建议更好的设计。否则,您必须创建方法public
或将类放在同一个包中。
答案 1 :(得分:2)
在Java中,即使在子类中,也不能在基类的不同实例上调用protected
方法:
public class C2 extends p1.C1 {
private C1 c1_instance;
public void doItAgain() {
doIt(); // fine
c1_instance.doIt(); // disallowed
}
}
唯一的例外是基类和子类都在同一个包中。
protected
修饰符指定只能访问该成员 在它自己的包中(与package-private一样),另外,通过 另一个包中其类的子类。
答案 2 :(得分:1)
受保护等同于包级别访问;如果您在不同的包中,则无法访问该方法。
你应该能够直接调用doIt()而不需要通过c1_instance对象,因为C2是一个子类。
来自http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
“protected修饰符指定只能在自己的包中访问该成员(与package-private一样),此外,还可以在另一个包中通过其类的子类访问。”
答案 3 :(得分:1)
C2可以是C1的子类,但这并不意味着它可以在不同的实例上访问这些方法,即c1_instance可能不是C2的实例。如果它在同一个包中,你可以访问它。
答案 4 :(得分:1)
不,protected
确保在同一个包和后代类中进行访问。您既不在同一个包中,也不是直接从后代类访问它。 C2
是后代,但c1_instance
不是。
答案 5 :(得分:0)
如果您的方法被声明为protected,那么您可以在此类中使用该包并在子类中访问它。
现在问题是,为什么在从其子类访问此受保护成员时会出现错误。答案是从子类访问受保护的方法,您的子类应直接从直接子类使用该方法。这里的直接子类是C2,但实例c1_instance不是。你可以直接使用这个方法(doIt()代替c1_instance.doIt())