为什么受保护的字段对子类不可见?

4

我有一个类:

package foo;
public abstract class AbstractClause<T>{
    protected T item;
    protected AbstractClause<T> next;
}

以及它的子类(在不同的包中):

package bar;
import foo.AbstractClause;

public class ConcreteClause extends AbstractClause<String>{

    public void someMethod(ConcreteClause c) {
        System.out.println(this.next);      // works fine
        System.out.println(c.next);         // also works fine
        System.out.println(this.next.next); // Error: next is not visible
    }
}

为什么?

5
可能重复:http://stackoverflow.com/questions/20534990/protected-variable-from-super-class-not-visible-from-subclass-in-different-packa https://dev59.com/lXA75IYBdhLWcg3w186G这些问题都涉及到Java中的protected访问修饰符。在Java中,如果一个成员变量或方法被声明为protected,那么它将只能在同一包或其子类中访问。因此,当一个子类试图从不同的包访问其超类的受保护成员时,编译器会发出访问错误。要解决这个问题,可以考虑将成员更改为公共的,并且在访问时,使用getter和setter方法来封装访问。 - user140547
它正在从子类中被访问。有什么问题吗? - user3663882
2
你是在编译时还是运行时出现了错误?因为我可以正常编译你的示例代码。 - sstan
2
以上代码没有问题。请提供精确的错误信息。 - NickJ
所以,基本上,根据其他 SO 问答,this.next 可以访问(正常情况下),但 this.last.next 不可访问,因为 this.last 引用了一个完全不同的实例,它不属于此实例的层次树。 - sstan
显示剩余6条评论
1个回答

3

看起来,如果子类在不同的包中,则方法只能访问其自己的受保护实例字段,而不能访问同一类的其他实例的字段。因此,this.lastthis.next可行,因为它们访问this对象的字段,但this.last.nextthis.next.last将无法工作。

public void append(RestrictionClauseItem item) {
    AbstractClause<Concrete> c = this.last.next; //Error: next is not visible
    AbstractClause<Concrete> d = this.next; //next is visible!
    //Some other staff
}

编辑 - 我的理解不完全正确,感谢点赞 :)

我做了一个实验。我有这个类:

public class Vehicle {
    protected int numberOfWheels;
}

这个是在不同的包裹中:

public class Car extends Vehicle {

  public void method(Car otherCar, Vehicle otherVehicle) {
    System.out.println(this.numberOfWheels);
    System.out.println(otherCar.numberOfWheels);
    System.out.println(otherVehicle.numberOfWheels); //error here!
  }
}

所以,重要的不是this。我可以访问同一类的其他对象的受保护字段,但不能访问超类型对象的受保护字段,因为超类型的引用可以持有任何对象,不一定是Car的子类型(如Bike),而Car无法访问从Vehicle继承的不同类型的受保护字段(它们仅对扩展类及其子类型可访问)。

你能详细解释一下“只能访问自己受保护的实例字段,而不能访问同一类的其他实例的字段”这部分吗?此外,我更新了 OP 代码以显示派生类可以访问其自己的字段以及其他派生类型实例的字段(请查看 System.out.println(c.next); 部分)。 - Pshemo
换句话说,protected 成员可以从 Derived 类的引用访问,但无法从 Parent 类的引用访问(这是有道理的,因为该引用可能持有与我们的 Derived 类型不同的实例,所以我们不能访问它)。 - Pshemo
1
@Pshemo 我错了 - 我已经更新了我的答案。 - NickJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接