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无法访问受保护的方法.并且 - 正如我们所看到的那样 - 当前从该包中对类进行子类化并不重要.也就是说后门闭合;)
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,它可能是 的另一个子类S2,C但它S不知道。写作S2时可能还没有出生。S因为S操纵受S2保护的内部结构是相当危险的。如果允许这样做,从S2的角度来看,它不知道谁会篡改其受保护的内部结构以及如何篡改,这使得S2job 很难推理其自身的状态。
现在如果obj是的D话,访问D extends S有危险吗?并不真地。如何使用是及其所有子类(包括. 因为超类有权利定义行为,而子类有义务接受和遵守。Sobj.memberSmemberSDSD
为了更容易理解,规则实际上应该简化为 requireobj的(静态)类型准确S。毕竟,子类D出现在S. 即使发生这种情况,objis的静态类型D,我们的简化规则也可以通过向上转换轻松处理它:((S)obj).member