随笔 - 1685  文章 - 624 评论 - 449 trackbacks - 0

故事背景

看过《哈利·波特》的娃们,想必一定还记得电影中的“隐形斗篷”。。这件隐形衣是哈利收到的圣诞礼物,也是死亡圣器中的三件套之一,它让哈利小盆友在执行任务的过程中简直是如虎添翼!

隐身衣揭秘--java中继承/隐藏/覆写

 

其实说白了,隐身衣所包裹的就是人类本能的掌控欲与窥探欲,我们渴望知道和了解所有事,但很多时候又不想让别人知道,所以我们需要“隐身衣”。。

 

隐身衣揭秘--java中继承/隐藏/覆写

 继承Inheritance/隐藏hide/覆写override

java中有继承Inheritance/隐藏hide/覆写override的概念,我们暂且不管他们的区别,先看看最近发生的一件小事,boss在开会时说错了一个数字,Leader赶紧说:”那是我弄错的“,程序猿想找到Boss说的数字时,却怎么也不行,这是怎么回事呢?请看案情回放:

public class Conference {
    public static void main(String[] args) {
        System.out.println(new Leader().sales);
    }
}
class Boss {
    public Integer sales=10000;
}
class Leader extends Boss{
    private Integer sales=9000;
}

咋一看,会打印Leader的销售量数据9000,但仔细分析来看,Leader类的sales变量是私有的,程序不能编译通过。该程序确实不能编译,但是错误出在Conference类中。原因:在Conference中调用的是new Leader()即leader的实例,不是Leader类,一个覆写方法的访问修饰符所提供的访问权限与被覆写方法的访问修饰符所提供的访问权限相比,至少要一样多[JLS 8.4.8.3]。

因为sales是一个域,所以Leader.sales隐藏(hide)了Boss.sales,而不是覆盖了它[JLS 8.3]。对一个域来说,当它要隐藏另一个域时,如果隐藏域的访问修饰符提供的访问权限比被隐藏域的少,尽管这么做不可取的,但是它确实是合法的。

其实我们还是可以找到老板的所说的sales的。如下:

public class Conference {
    public static void main(String[] args) {
        System.out.println(((Boss)new Leader()).sales);
    }
}
class Boss {
    public Integer sales=10000;
}
class Leader extends Boss{
    private Integer sales=9000;
}

总结

覆写与隐藏之间的一个非常大的区别。一旦一个方法在子类中被覆写,你就不能在子类的实例上调用它了(除了在子类内部,通过使用super 关键字来方法)。然而,你可以通过将子类实例转型为某个超类类型来访问到被隐藏的域,在这个超类中该域未被隐藏。

参考资料

【1】java解惑

【2】https://www.sohu.com/a/231064552_764920

posted on 2019-10-18 09:14  一天不进步,就是退步  阅读(...)  评论(...编辑  收藏