根据我的理解,受保护的方法可以被同一个包中的任何类访问,但只有该类的子类可以从其他包访问。
package Parent;
public class Parent {
protected void display() {
//Code here
}
}
import Parent;
package Child;
class Child extends Parent{
void view(Parent p1) {
this.display(); // Success
p1.display(); // Error
}
void next(Parent p2) {
p2.foo(); //Success
}
}
此处this.display()
成功,因为子类负责实现。但是p1.display()
不起作用,因为p1
不属于Child
类。
在从同一个包中的类访问受保护的方法的情况下,我们如何证明这种行为?
答案 0 :(得分:2)
你的
p1.display();
有可能运行在任何包中实现的方法,具体取决于您收到的确切Parent
子类。这明显违反了protected
背后的意图,这意味着允许为扩展设计的类为其子代提供封装的方法。
如果允许该调用,对于一个流氓类来说,从完全陌生的类中访问封装的方法将非常容易。
答案 1 :(得分:1)
如果你使用super.display()
它会起作用。原因是父类中的protected
方法始终对子类可见,无论它们是否在同一个包中。当你只说p1.display()
时,它希望该方法是公开的,因为两个类都在不同的包中。
请阅读以下内容以加深对此的理解。
In Java, difference between default, public, protected, and private
答案 2 :(得分:1)
您提供的示例是使用传递给子项的Parent
实例调用该方法。规范声明当范围受到保护时,对字段或实例方法的访问必须来自子类。请注意规范的部分,access is permitted if and only if the type of the expression Q is S or a subclass of S
。在您的示例中,ExpressionName是p1,它是Parent
的实例,使其类型不是Child
或子类为Child
,因此不允许访问。
设C是声明受保护成员的类。访问是 只允许在C的子类S的主体内使用。
此外,如果Id表示实例字段或实例方法,则:
如果访问是通过限定名称Q.Id进行的,其中Q是ExpressionName,那么当且仅当类型允许时才允许访问 表达式Q是S或S的子类。
如果访问是通过字段访问表达式E.Id,其中E是主表达式,或通过方法调用表达式E.Id(...), 其中E是主表达式,如果和,则允许访问 只有当E的类型是S或S的子类时。
我认为,当我们将Child
的实例传递给Parent
上的方法时,我会看到您尝试制作的要点,因为Parent
是Child
的子类我们应该能够调用其受保护的方法。规范的规则禁止这样做。