来自java中不同软件包的受保护成员访问 - 好奇心

2022-09-03 13:23:43
package packageOne;
public class Base
{
    protected void display(){
        System.out.println("in Base");
    }
}


package packageTwo;
public class Derived extends packageOne.Base {
    public void show(){
        new Base().display(); //this is not working throws compilation error that display() from the type Base is not visible
        new Derived().display(); //is working
        display(); //is working
    }
}

这两个包位于两个不同的文件中。但为什么会有这种行为呢?


答案 1

protected允许从子类同一包中的其他类进行访问。这就是为什么任何类实例都可以访问 中的受保护方法的原因。DerivedBase

另一行创建一个实例(不是实例!!)。并且只允许从同一包的对象访问该实例的受保护方法。BaseDerived


display();

-> 允许,因为 调用方,实例有权访问其子类的受保护成员和字段,即使它们位于不同的包中Derived

new Derived().display();

-> 允许,因为您在 的实例上调用该方法,并且该实例有权访问其子类的受保护方法Derived

new Base().display();

-> 不允许,因为调用方(实例)类不是在与类相同的包中定义的,因此无法访问受保护的方法。正如我们所看到的,当前从该包中子类化类并不重要。该后门已关闭;)thisBasethis


答案 2

http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6

class C
    protected member;

// in a different package

class S extends C 

    obj.member; // only allowed if type of obj is S or subclass of S

动机可能如下。如果 是 一个 ,类对其内部有足够的了解,它有权操纵其成员,并且可以安全地执行此操作。objSS

如果不是 ,则可能是 的另一个子类,它不知道。 可能在写作时甚至还没有出生。因为操纵 受保护的内部是相当危险的。如果允许这样做,从 的角度来看,它不知道谁会篡改其受保护的内部以及如何篡改,这使得工作很难解释它自己的状态。objSS2CSS2SSS2S2S2

现在,如果 是 和 ,访问是否有危险?没有。如何使用是及其所有子类(包括 . 因为超类有权定义行为,并且子类有义务接受和服从。objDD extends SSobj.memberSmemberSDSD

为了便于理解,应该真正简化规则,以要求 的(静态)类型完全正确。毕竟,子类出现在 中是非常不寻常和不合适的。即使发生这种情况,静态类型是,我们的简化规则也可以通过上转换轻松处理它:objSDSobjD((S)obj).member


推荐