重写
父类的方法被子类继承后,为了更恰当的描述子类的行为特征,子类重新定义父类的方法,这种对父类方法进行改写或改造的现象叫做方法重写或方法覆盖;
public class Father {
public void work() {
System.out.println("正在上班......");
}
}
public class Son extends Father{
public void work() { //子类重写父类的 work 方法
System.out.println("正在上学......");
}
public static void main(String[] args) {
Son son = new Son();
son.work();
}
}
正在上学......
不能重写的情况
一般情况下父类的方法都可以被子类重写,但是有几种情况例外:
public class Father {
public static void work() {
System.out.println("正在上班......");
}
}
public class Son extends Father{
public void work() { //这里报错,父类静态方法子类无法重写
System.out.println("正在上学......");
}
public static void main(String[] args) {
Son son = new Son();
son.work();
}
}
当父类的方法是静态方法(即被static修饰)时,子类不能重写父类方法,即使子类同样也加上static也不是重写,只是新定义了子类的一个静态方法;
public class Father {
public static void work() {
System.out.println("正在上班......");
}
}
public class Son extends Father{
@Override
public static void work() { //因为有 Override,这里还是报错
System.out.println("正在上学......");
}
public static void main(String[] args) {
Son son = new Son();
son.work();
}
}
@Override 是用来判断子类一个方法是否重写了父类的方法,上例代码中虽然子类的静态方法和父类的很接近,但也不是重写,只是简单的定义了一个静态方法而已;
当父类的方法被 final 修饰时,子类只能继承该方法而不能重写该方法;
public class Father {
public final void work() {
System.out.println("正在上班......");
}
}
public class Son extends Father{
/*public void work() { //不注释掉会报错
System.out.println("正在上学......");
}*/
public static void main(String[] args) {
Son son = new Son();
son.work();
}
}
正在上班......
上例中注释掉的部分如果不被注释,则会报错,因为无法重写,但是,根据执行结果我们可以发现,虽然父类中被 final 修饰的方法子类不能重写,但是可以继承并使用;
public class Father {
public void work() {
System.out.println("正在上班......");
}
}
public class Son extends Father{
public void work() {
super.work();
System.out.println("正在上学......");
}
public static void main(String[] args) {
Son son = new Son();
son.work();
}
}
正在上班......
正在上学......
如果想要调用已被子类重写的父类的方法,可以使用 super 关键字调用, super 还可以用在非静态代码块中,切记,不可用在静态代码块中。
重写时要注意
- 子类重写的方法名要与父类被重写的方法名相同,且参数列表(参数类型和参数个数)也要相同;
- 子类重写父类方法时不得增加 static 修饰符;
- 返回值:a、当父类方法的返回值类型为 void 或者为基本数据类型,则子类重写方法的返回值类型要与父类被重写方法返回值类型相同;b、当父类方法的返回值类型为引用数据类型,则子类重写方法的返回值类型要与父类被重写的方法的返回值类型相同或者是其子类;
- 访问控制符;子类重写方法的访问控制符不能缩小父类被重写方法的访问控制符范围,即子类重写方法的访问控制符必须大于或等于父类被重写方法的访问控制符。