3

我刚刚遇到涉及受保护修饰符的奇怪错误。

我有以下代码:

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

这不是一个错误吗?

4

6 回答 6

4

我也对protected“可从同一个包或子类访问”的印象有印象,但Java 语言规范当然更精确,并在 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或将类放在同一个包中。

于 2011-09-08T10:44:24.170 回答
2

在 Java 中,您不能在基类的不同实例上protected调用方法,即使在子类中也是如此:

public class C2 extends p1.C1 {
    private C1 c1_instance;
    public void doItAgain() {
        doIt();             // fine
        c1_instance.doIt(); // disallowed
    }
}

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

引用Java OO 教程

修饰符指定该protected成员只能在其自己的包中访问(与 package-private 一样),此外,它的类在另一个包中的子类也可以访问。

于 2011-09-08T10:26:14.157 回答
1

protected 相当于包级访问;如果您在不同的包中,则无法访问该方法。

但是,您应该能够直接调用 doIt() 而无需通过 c1_instance 对象,因为 C2 是一个子类。

来自http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

“受保护的修饰符指定该成员只能在其自己的包中访问(与包私有一样),此外,它的类在另一个包中的子类也可以访问。”

于 2011-09-08T10:25:04.077 回答
1

C2 可能是 C1 的子类,但这并不意味着它可以在不同的实例上访问这些方法,即 c1_instance 可能不是 C2 的实例。如果它在同一个包中,您可以访问它。

于 2011-09-08T10:25:40.107 回答
1

不,protected确保在同一个包和后代类中的访问。您既不在同一个包中,也没有直接从后代类访问它。C2是后代,但c1_instance不是。

于 2011-09-08T10:26:16.520 回答
0

如果您的方法被声明为受保护,那么您可以在此类、包和子类中访问它。

现在的问题是,尽管从其子类访问此受保护成员,为什么会出现错误。答案是从子类访问受保护的方法,您的子类应该直接使用直接子类中的方法。这里的直接子类是 C2 但实例 c1_instance 不是。您可以直接使用此方法(doIt() 代替 c1_instance.doIt())

于 2011-09-08T11:18:25.283 回答