受保护的成员访问java中不同的包 - 一个好奇心

abs*_*son 14 java protected

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这两个包有两个不同的文件.但为什么会这样呢?

And*_*s_D 14

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

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


display();
Run Code Online (Sandbox Code Playgroud)

- > 允许,因为调用者,一个实例Derived可以访问受保护的成员及其子类的字段,即使它们位于不同的包中

new Derived().display();
Run Code Online (Sandbox Code Playgroud)

- > allowed,因为你在一个实例上调用该方法,Derived并且该实例可以访问其子类的受保护方法

new Base().display();
Run Code Online (Sandbox Code Playgroud)

- > 不允许因为调用者的(this实例)类没有像Base类一样在同一个包中定义,所以this无法访问受保护的方法.并且 - 正如我们所看到的那样 - 当前从该包中对类进行子类化并不重要.也就是说后门闭合;)


irr*_*ble 3

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
Run Code Online (Sandbox Code Playgroud)

其动机大概如下。如果obj是一个S,那么类S对其内部结构有足够的了解,它就有权操纵其成员,并且可以安全地做到这一点。

如果obj不是S,它可能是 的另一个子类S2C但它S不知道。写作S2时可能还没有出生。S因为S操纵受S2保护的内部结构是相当危险的。如果允许这样做,从S2的角度来看,它不知道谁会篡改其受保护的内部结构以及如何篡改,这使得S2job 很难推理其自身的状态。

现在如果obj是的D话,访问D extends S有危险吗?并不真地。如何使用是及其所有子类(包括. 因为超类有权利定义行为,而子类有义务接受和遵守。Sobj.memberSmemberSDSD

为了更容易理解,规则实际上应该简化为 requireobj的(静态)类型准确S。毕竟,子类D出现在S. 即使发生这种情况,objis的静态类型D,我们的简化规则也可以通过向上转换轻松处理它:((S)obj).member