来自相同和不同包的受保护方法调用之间的区别

时间:2013-06-05 09:46:42

标签: java

根据我的理解,受保护的方法可以被同一个包中的任何类访问,但只有该类的子类可以从其他包访问。

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类。 在从同一个包中的类访问受保护的方法的情况下,我们如何证明这种行为?

3 个答案:

答案 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上的方法时,我会看到您尝试制作的要点,因为ParentChild的子类我们应该能够调用其受保护的方法。规范的规则禁止这样做。

Specification