java static 方法重写_浅谈java中静态方法的重写问题详解

首先来看看以下程序将会打印出什么:

class Dog {

public static void bark() {

System.out.print("woof ");

}

}

class Basenji extends Dog {

public static void bark() { }

}

public class Bark {

public static void main(String args[]) {

Dog woofer = new Dog();

Dog nipper = new Basenji();

woofer.bark();

nipper.bark();

}

}

随意地看一看,好像该程序应该只打印一个woof。毕竟,Basenji扩展自Dog,并且它的bark方法定义为什么也不做。main方法调用了bark方法,第一次是在Dog类型的woofer上调用,第二次是在Basenji类型的nipper上调用。巴辛吉小鬣狗并不会叫唤,但是很显然,这一只会。如果你运行该程序,就会发现它打印的是woof woof。这只可怜的小家伙到底出什么问题了?

问题在于bark是一个静态方法,而对静态方法的调用不存在任何动态的分派机制[JLS 15.12.4.4]。当一个程序调用了一个静态方法时,要被调用的方法都是在编译时刻被选定的,而这种选定是基于修饰符的编译期类型而做出的,修饰符的编译期类型就是我们给出的方法调用表达式中圆点左边部分的名字。在本案中,两个方法调用的修饰符分别是变量woofer和nipper,它们都被声明为Dog类型。因为它们具有相同的编译期类型,所以编译器使得它们调用的是相同的方法:Dog.bark。这也就解释了为什么程序打印出woof woof。尽管nipper的运行期类型是Basenji,但是编译器只会考虑其编译器类型。

要订正这个程序,直接从两个bark方法定义中移除掉static修饰符即可。这样,Basenji中的bark方法将覆写而不是隐藏Dog中的bark方法,而该程序也将会打印出woof,而不是woof woof。通过覆写,你可以获得动态的分派;而通过隐藏,你却得不到这种特性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值