Java保护修饰符

时间:2011-09-08 10:22:55

标签: java jls

我有一个奇怪的错误,涉及保护修饰符。

我有以下代码:

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()方法。

这不是一个错误吗?

6 个答案:

答案 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
    }
}

唯一的例外是基类和子类都在同一个包中。

引用Java OO tutorial

  

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())