使用子类引用访问包外的受保护成员

时间:2018-05-20 10:39:25

标签: java protected access-modifiers

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

我已经浏览了博客和许多堆栈溢出答案,但没有找到任何答案为什么?。

所以任何人都可以帮助我知道为什么答案?

2 个答案:

答案 0 :(得分:3)

您不能访问A,因为您仍然在子类或包的 之外。 main方法为static,因此不会绑定B类的实例。要访问A,您需要 B类,所以在非静态上下文中

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

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

Java语言规范中描述了protected的详细信息。摘自JLS§6.6.2

  

对象的protected成员或构造函数可以从包外部访问,只能通过负责该对象的实现的代码来声明它。

     

C成为声明protected成员的类。仅在S的子类C允许访问权限。

这种限制甚至超出了你的范例。关键是" 负责实施"。将其与以下示例进行比较:

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

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的实现负责。因此,不允许访问。

答案 1 :(得分:0)

继承/多态的概念使得继承的父类的公共和受保护的方法和变量——子类的成员,因此可以被子类的对象访问。受保护的访问需要两条规则-

  1. 只能被同一个包内的类访问

  2. 可以通过继承访问。

    A a = new B();

    a.m1(); //不编译

这是 B 类的一个实例,但就 A 的引用而言,它是一个 A 对象。这就是为什么对象“a”只能访问 A 和 B 共有的成员。即对象“a”作为类 A 的引用只能访问类 B 的继承方法。它不能访问任何B 的方法或类变量,即使它是类 B 的一个实例,它也不存在于 A 中。您必须将其显式转换为 B 以使其访问类 B 的唯一方法和变量。因此,请记住这一点,就Java而言,对象“a”是另一个包中的A类对象。因此,即使方法 a.m1 被继承,“a”也无法访问它,因为它是另一个包中的 A 对象。 a.m1 将在 pack1 中编译。

与此代码对比

B b = new B();
b.m1() //compiles

b 是 B 的对象,因此受保护访问的规则 2 适用。由于 m1 是对象 B 的继承保护方法,因此它可以完全访问它。