父类中的方法在子类中必须可见,即子类继承了父类中的该方法(可以显式的使用 super 关键字来访问父类中的被重写的方法),如果父类中的方法为 private 类型的,那么子类虽能继承,但无法覆盖
子类和父类的方法必须是实例方法,如果父类是 static 方法而子类是实例方法,或者相反都会报错。如果父类和子类都是 static 方法,那么子类隐藏父类的方法,而不是重写父类方法
子类和父类的方法必须要具有相同的函数名称、参数列表,并且子类的返回值与父类相同或者是父类返回类型的子类型(jdk1.5 之后)。如果方法名称相同而参数列表不同(返回类型可以相同也可以不同),那么只是方法的重载,而非重写。如果方法名称和参数列表相同,返回值类型不同,子类返回值类型也不是父类返回值类型的子类,编译器就会报错
子类方法的访问权限不能小于父类方法的访问权限(可以具有相同的访问权限或者子类的访问权限大于父类)。访问权限由高到低:public、protected、包访问权限、private。如果子类方法的访问权限低于父类,则编译器会给出错误信息
子类方法不能比父类方法抛出更多的编译时异常(不是运行时异常),即子类方法抛出的编译时异常或者和父类相同或者是父类异常的子类。当然,子类也可以不抛出异常,或者抛出 RuntimeException 异常
不能重写被标识为 final 的方法。final 方法可以被继承,但不能被重写。一个方法如果被 final 修饰就意味着这个方法不会被改动
为何子类重写方法的访问权限不能低于父类中权限
因为向上转型及 Java 程序设计维护的原因
假设一个父类 A 拥有的方法 public void setXXX() {}
可以被其他任意对象调用
这个方法被子类 B 覆写后为 void setXXX() {}
即默认的访问权限只能被本包极其子类所访问
假设其他包中的对象 C 调用方法:
void get(A a) {
a.setXXX();
}
假设此时传入的对象为 B 类对象 b,此时 b 将转型为 a 但是 b 中的 setXXX() 调用权限已经被缩小了这将造成错误。所以子类对象不能比父类对象访问权限小
为何子类重写方法的返回类型必须与父类相同或者是父类返回类型的子类型
也是因为向上转型
假设 B 是 A 的子类,初始化 a 为 B 类型,并调用 B 类重写过的方法 func():
A a = new B();
C aa = a.func();
假设原本 A 类的 func() 方法返回类型为 C,那么 B 类的 func() 方法返回类型就只能是 C 类或 C 类的子类型了
为何子类方法不能比父类方法抛出更多的编译时异常
子类在覆盖父类方法的时候,父类的引用可以调用该方法。如果父类的引用调用子类的方法,那么这个多抛出来的异常,就可能处于一种无法被处理的状态