package pack1;
class A{
   protected void m1(){
      System.out.println("protected modifier");
   }
}

package pack2;
class B extends A{
    public static void main(string[]args){
         B b = new B();//Valid
         b.m1();

        A a = new B();//Invalid
          a.m2();

       A a1 = new A();//InValid
         a1.m1();

   }
}


为什么在访问包外的受保护成员时,我们只需要引用子类即可?

为什么我们不能使用父引用来访问受保护的成员(这里A a = new B())?

我浏览了博客和许多堆栈溢出答案,但是找不到任何答案。

所以有人可以帮助我知道为什么的答案吗?

最佳答案

不允许您访问A,因为您仍然不在子类或包中。 main方法是static,因此不受B类实例的约束。为了访问A,您需要位于B类中,因此在非静态上下文中,例如

public class B extends A {
    public void foo() {
        m1(); // Valid call since inside subclass
    }
}


我认为您误解了static的含义。



protected的详细信息在Java语言规范中进行了描述。从JLS§6.6.2中摘录:


  对象的protected成员或构造函数可以从仅由负责该对象实现的代码声明的包外部访问。
  
  假设C是声明protected成员的类。仅在S的子类C的主体内允许访问。


限制甚至超出了您的示例。关键是“负责实施”。将其与以下示例进行比较:

package a;

public class Point {
    protected int x;
    protected int y;
}




package b;

import a.Point;

public class Point3D extends Point {
    public void delta(Point other) {
        other.x += this.x;  // Compile-time error: Cannot access other.x
        other.y += this.y;  // Compile-time error: Cannot access other.y
    }
}


尽管类Point3DPoint的子类,但它不负责other对象的实现。因此,不允许访问其protected成员。

相同的

public class B extends A {
    public void foo() {
        A other = new A();
        other.m1(); // Compile-time error
    }
}


因为foo()方法调用所属的当前实例不负责other的实现。因此,不允许访问。

09-17 17:25
查看更多