重写方法的规则:
-变元列表必须与被重写的方法的变元列表完全匹配。如果不匹配,则得到的可能就是一个意想不到的重载方法。
-返回类型必须与超类中被重写方法中原先声明的返回类型或子类型相同。
-访问级别的限制性一定不能被重写方法的更严格。
-访问级别的限制性可以比重写方法的弱 (child - public ,parent - protected)
-仅当实例方法被子类继承时,它们才能被重写。与实例的超类位于相同包内的子类一重写为标志为private或final的任何超类方法。不同包中的子类只能重写那些标志为private或final的任何超类方法。不同包中的子类只能重写那些标志位public或protected的非final的方法(因为protected方法是由子类继承的) 。
-重写方法可以抛出任何未检验(运行时)异常,无论被重写方法是否声明了改异常。
-重写方法一定不能抛出比。重写方法声明的检验异常更新或更广的检验异常。(Child - RuntimeException, Parent - Exception)
-不能重写标志为final的方法
-不能重写标识为static的方法 。
-如果方法不能被继承,就不能就不能重写它。
例如:
调用重写方法的超类版本
很多时候,你可能想利用方法的超类按本中的一些代码,并希望重写它以提供一些其他的特定行为。这好像是说:“运行方法的超类版本,然后回到这里,完成我的子类的附加方法代码。” 。这在代码中可以使用关键字super轻松实现,如下所示:
注意,使用super调用重写方法只是用于实例方法(记住,静态方法不能被重写) 。
考试注意事项 如果一个方法被重写,但是你使用多态(超类型)引用来引用具有重写方法的子类对象,编译器就会认为你正在调用该方法的超类型版本。如果超累型版本声明一个检验异常,但是重写的子类型的方法没有这样做,那么编译任然认为你正在底啊用一个声明了异常的方法。请看下面的例子: class Animal { public void eat(){ // throws an Exception } } class Dog2 extends Animal { public void eat(){ /*no Exception*/} public static void main(String[] args){ Animal a = new Dog2(); Dog2 d = new Dog2(); a.eat(); // compiler error – unreported exception d.eat(); // ok } } 由于Animal的eat()方法上声明了Exception,因而这段代码不会通过编译。及时在运行时也会发生这种情况,使用的eat()方法将会是Dog2版本,它没有声明异常。 |
合法的和非法的方法重写例子
让我们
看一下重写的Animal的eat()方法:
下表列出了Animal的eat()方法的非法重写例子,它以Animla类之前的版本为基础。
非法的重写代码 | 代码中的错误 |
private void eat(){} | 访问修饰符限制性更强 |
private void eat() throws Exception{} | 超类版本中没有声明检验异常 |
private void eat(String food){} | 合法的重载,但不是重写,因为变元列表变了 |
public String eat(){} | 不是重写,因为其返回类型改变了。也不是重载,因为变元列表没有变化 |