难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJ IDEA v2018.3
提示
本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
1.@Override重写方法
子类中具有相同签名(方法名,加上其参数的数量和类型)和返回类型的实例方法作为父类中的实例方法时会重写父类的方法。
重写方法时,请使用@Override注解来指示编译器您要重写父类中的方法。
上图中,子类Student重写了父类People实例方法sayHi。
2.重写离子类最近的父类方法
我们先来看一个继承关系:
Student类继承Man类,Man类继承People类。
People类:
Man类:
Student类:
子类重写方法的能力允许类从“足够接近”的父类继承行为,然后根据需要修改行为。重写方法具有相同的名称,参数的数量和类型和返回类型作为它重写的方法。
上面程序中,Man类重写了People类的sayHi方法,Student类重写了Man类的sayHi方法。它们总是重写最接近的父类方法。
3.重写方法方法签名必须一致
重写方法父类方法时,方法签名必须一致。
关系继承UML类图:
演示:
重写父类方法。
实现:
People类:
Student类:
Main类:
结果:
从运行结果来看,准确无误。
假如,重写方法时方法签名不一致,会怎样?
People类无需修改。
修改Student类:
Main类无需修改。
结果:
咦?你不是说方法签名必须一直吗?怎么不一致还可以运行?
首先,方法签名指的是方法名和参数列表(参数数量及类型),参数名称不参与在内,所以这个还是方法签名一致。
继续修改Student类:
结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(13, 5) java: 方法不会覆盖或实现超类型的方法
错误原因:参数类型不一致。
继续修改Student类:
结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(13, 5) java: 方法不会覆盖或实现超类型的方法
错误原因:参数列表个数不一样。
继续修改Student类:
结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(13, 5) java: 方法不会覆盖或实现超类型的方法
错误原因:方法名不一致。
4.重写方法返回值类型可以是返回值类型的子类型
重写方法还可以返回由重写方法返回的类型的子类型。此子类型称为协变返回类型。
演示:
重写方法还可以返回由重写方法返回的类型的子类型。
思路:
返回值类型是动物(Animal),动物子类有狗(Dog)、猫(Cat)。
实现:
Animal类:
Dog类:
Cat类:
People类:
Student类:
Main类:
结果:
从运行结果来看,准确无误。
上面父类People里的sayHi方法返回的是Animal,子类Student重写sayHi方法返回的也是Animal。运行正常。
下面我们把子类Student重写sayHi方法的返回值类型改为Dog或者Cat看看:
其他类不用修改。
修改Student类:
结果:
运行正常。
但是,反过来,“重写方法返回值类型可以是返回值类型的父类类型”就不行。下面我们试试。
其他类不用修改。
修改People类:
修改Student类:
结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(14, 19) java: lab.Student中的sayHi(java.lang.String)无法覆盖lab.People中的sayHi(java.lang.String) 返回类型lab.Animal与lab.Cat不兼容Error:(13, 5) java: 方法不会覆盖或实现超类型的方法
我们看到类型不兼容,通俗来讲,就是狗一定是动物,动物不一定是狗。
5.类方法在继承中的变化
如果子类定义的类方法与父类中的类方法具有相同的签名,则子类中的方法会隐藏父类中的方法。
隐藏类方法和重写实例方法之间的区别具有重要意义:
被调用的重写实例方法的版本是子类中的版本。
被调用的隐藏静态方法的版本取决于它是从超类还是从子类调用的。
演示:
子类与父类中的类方法方法签名相同时,造成的效果是隐藏,不是重写。
实现:
People类:
Student类:
Main类:
结果:
结果可能和大家想的不一样。
类方法调用看左边,实例方法调用看右边。
另外,类方法无法用@Override注解:
修改Student类:
结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(21, 5) java: 不能使用 @Override 注释静态方法
静态方法不是重写,是隐藏。
6.访问修饰符
子类重写方法的访问修饰符只能比父类访问修饰符权限大,不能小。 例如,父类中的受保护实例方法可以在子类中公开,但不能是私有的。
演示:
重写方法访问权限由protected变为public。
实现:
People类:
Student类:
Main类:
结果:
从运行结果来看,准确无误。
如果我们将protected改为private呢?
其他类不用修改。
修改Student类:
结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/lab/Student.java
Error:(14, 18) java: lab.Student中的sayHi(java.lang.String)无法覆盖lab.People中的sayHi(java.lang.String)
正在尝试分配更低的访问权限; 以前为protected
Error:(21, 25) java: lab.Student中的sayHello(java.lang.String)无法覆盖lab.People中的sayHello(java.lang.String)
正在尝试分配更低的访问权限; 以前为protected
无法设置为比父类方法更低的访问权限。
7.静态与非静态之间的更改
如果尝试将父类中的实例方法更改为子类中的静态方法,则会出现编译时错误,反之亦然。
演示:
将父类中的实例方法更改为子类中的静态方法。
将父类中的静态方法更改为子类中的非静态方法。
实现:
People类:
Student类:
Main类:
结果:
错误信息:
文字版:
/Users/admin/Workspace/Java/Hello/src/lab/Student.java
Error:(14, 24) java: lab.Student中的sayHi(java.lang.String)无法覆盖lab.People中的sayHi(java.lang.String)
覆盖的方法为 static
Error:(13, 5) java: 不能使用 @Override 注释静态方法
Error:(21, 17) java: lab.Student中的sayHello(java.lang.String)无法覆盖lab.People中的sayHello(java.lang.String)
被覆盖的方法为static
Error:(14, 24) java: lab.Student中的sayHi(java.lang.String)无法覆盖lab.People中的sayHi(java.lang.String) 覆盖的方法为 static
你要重写的方法是static的,指的是Student类中的sayHi方法:
Error:(21, 17) java: lab.Student中的sayHello(java.lang.String)无法覆盖lab.People中的sayHello(java.lang.String) 被覆盖的方法为static
被重写的方法是静态的,而你的是非静态的。被重写的方法在People类中,代码如下:
总结
- 子类中具有相同签名(方法名,加上其参数的数量和类型)和返回类型的实例方法作为父类中的实例方法时会重写父类的方法。
- 重写方法时,请使用@Override注解来指示编译器您要重写父类中的方法。
- 子类重写方法的能力允许类从“足够接近”的父类继承行为,然后根据需要修改行为。重写方法具有相同的名称,参数的数量和类型和返回类型作为它重写的方法。
- 重写方法还可以返回由重写方法返回的类型的子类型。此子类型称为协变返回类型。
- 如果子类定义的类方法与父类中的类方法具有相同的签名,则子类中的方法会隐藏父类中的方法。
- 隐藏类方法和重写实例方法之间的区别具有重要意义:(一)被调用的重写实例方法的版本是子类中的版本。(二)被调用的隐藏静态方法的版本取决于它是从超类还是从子类调用的。
- 子类重写方法的访问修饰符只能比父类访问修饰符权限大,不能小。 例如,父类中的受保护实例方法可以在子类中公开,但不能是私有的。
- 如果尝试将父类中的实例方法更改为子类中的静态方法,则会出现编译时错误,反之亦然。
至此,Java中重写方法@Override相关内容讲解先告一段落,更多内容请持续关注。
答疑
如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。
上一章
下一章
“全栈2019”Java第四十九章:重载与重写对比详解
学习小组
加入同步学习小组,共同交流与进步。
- 方式一:关注头条号Gorhaf,私信“Java学习小组”。
- 方式二:关注公众号Gorhaf,回复“Java学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
版权声明
原创不易,未经允许不得转载!