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())?
我已经浏览了博客和许多堆栈溢出答案,但没有找到任何答案为什么?。
所以任何人都可以帮助我知道为什么答案?
答案 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
}
}
虽然类Point3D
是Point
的子类,但它不负责other
对象的实现。因此,不允许访问其protected
成员。
相同
public class B extends A {
public void foo() {
A other = new A();
other.m1(); // Compile-time error
}
}
因为foo()
方法调用所属的当前实例不对other
的实现负责。因此,不允许访问。
答案 1 :(得分:0)
继承/多态的概念使得继承的父类的公共和受保护的方法和变量——子类的成员,因此可以被子类的对象访问。受保护的访问需要两条规则-
只能被同一个包内的类访问
可以通过继承访问。
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 的继承保护方法,因此它可以完全访问它。