“全栈2019”Java第四十八章:重写方法Override

1,525 阅读8分钟
原文链接: www.toutiao.com

难度

初级

学习时间

30分钟

适合人群

零基础

开发语言

Java

开发环境

  • JDK v11
  • IntelliJ IDEA v2018.3

提示

本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。

1.@Override重写方法

“全栈2019”Java第四十八章:重写方法Override

子类中具有相同签名(方法名,加上其参数的数量和类型)和返回类型的实例方法作为父类中的实例方法时会重写父类的方法。

重写方法时,请使用@Override注解来指示编译器您要重写父类中的方法。

上图中,子类Student重写了父类People实例方法sayHi。

2.重写离子类最近的父类方法

我们先来看一个继承关系:

“全栈2019”Java第四十八章:重写方法Override

Student类继承Man类,Man类继承People类。

People类:

“全栈2019”Java第四十八章:重写方法Override

Man类:

“全栈2019”Java第四十八章:重写方法Override

Student类:

“全栈2019”Java第四十八章:重写方法Override

子类重写方法的能力允许类从“足够接近”的父类继承行为,然后根据需要修改行为。重写方法具有相同的名称,参数的数量和类型和返回类型作为它重写的方法。

上面程序中,Man类重写了People类的sayHi方法,Student类重写了Man类的sayHi方法。它们总是重写最接近的父类方法。

3.重写方法方法签名必须一致

重写方法父类方法时,方法签名必须一致。

关系继承UML类图:

“全栈2019”Java第四十八章:重写方法Override

演示:

重写父类方法。

实现:

People类:

“全栈2019”Java第四十八章:重写方法Override

Student类:

“全栈2019”Java第四十八章:重写方法Override

Main类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

从运行结果来看,准确无误。

假如,重写方法时方法签名不一致,会怎样?

People类无需修改。

修改Student类:

“全栈2019”Java第四十八章:重写方法Override

Main类无需修改。

结果:

“全栈2019”Java第四十八章:重写方法Override

咦?你不是说方法签名必须一直吗?怎么不一致还可以运行?

首先,方法签名指的是方法名和参数列表(参数数量及类型),参数名称不参与在内,所以这个还是方法签名一致。

继续修改Student类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

错误信息:

“全栈2019”Java第四十八章:重写方法Override

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(13, 5) java: 方法不会覆盖或实现超类型的方法

错误原因:参数类型不一致。

继续修改Student类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

错误信息:

“全栈2019”Java第四十八章:重写方法Override

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(13, 5) java: 方法不会覆盖或实现超类型的方法

错误原因:参数列表个数不一样。

继续修改Student类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

错误信息:

“全栈2019”Java第四十八章:重写方法Override

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(13, 5) java: 方法不会覆盖或实现超类型的方法

错误原因:方法名不一致。

4.重写方法返回值类型可以是返回值类型的子类型

重写方法还可以返回由重写方法返回的类型的子类型。此子类型称为协变返回类型。

演示:

重写方法还可以返回由重写方法返回的类型的子类型。

思路:

返回值类型是动物(Animal),动物子类有狗(Dog)、猫(Cat)。

实现:

Animal类:

“全栈2019”Java第四十八章:重写方法Override

Dog类:

“全栈2019”Java第四十八章:重写方法Override

Cat类:

“全栈2019”Java第四十八章:重写方法Override

People类:

“全栈2019”Java第四十八章:重写方法Override

Student类:

“全栈2019”Java第四十八章:重写方法Override

Main类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

从运行结果来看,准确无误。

上面父类People里的sayHi方法返回的是Animal,子类Student重写sayHi方法返回的也是Animal。运行正常。

下面我们把子类Student重写sayHi方法的返回值类型改为Dog或者Cat看看:

其他类不用修改。

修改Student类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

运行正常。

但是,反过来,“重写方法返回值类型可以是返回值类型的父类类型”就不行。下面我们试试。

其他类不用修改。

修改People类:

“全栈2019”Java第四十八章:重写方法Override

修改Student类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

错误信息:

“全栈2019”Java第四十八章:重写方法Override

文字版:

/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类:

“全栈2019”Java第四十八章:重写方法Override

Student类:

“全栈2019”Java第四十八章:重写方法Override

Main类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

结果可能和大家想的不一样。

类方法调用看左边,实例方法调用看右边。

另外,类方法无法用@Override注解:

修改Student类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

错误信息:

“全栈2019”Java第四十八章:重写方法Override

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Student.javaError:(21, 5) java: 不能使用 @Override 注释静态方法

静态方法不是重写,是隐藏。

6.访问修饰符

子类重写方法的访问修饰符只能比父类访问修饰符权限大,不能小。 例如,父类中的受保护实例方法可以在子类中公开,但不能是私有的。

演示:

重写方法访问权限由protected变为public。

实现:

People类:

“全栈2019”Java第四十八章:重写方法Override

Student类:

“全栈2019”Java第四十八章:重写方法Override

Main类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

从运行结果来看,准确无误。

如果我们将protected改为private呢?

其他类不用修改。

修改Student类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

错误信息:

“全栈2019”Java第四十八章:重写方法Override

文字版:

/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类:

“全栈2019”Java第四十八章:重写方法Override

Student类:

“全栈2019”Java第四十八章:重写方法Override

Main类:

“全栈2019”Java第四十八章:重写方法Override

结果:

“全栈2019”Java第四十八章:重写方法Override

错误信息:

“全栈2019”Java第四十八章:重写方法Override

文字版:

/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方法:

“全栈2019”Java第四十八章:重写方法Override

Error:(21, 17) java: lab.Student中的sayHello(java.lang.String)无法覆盖lab.People中的sayHello(java.lang.String) 被覆盖的方法为static

被重写的方法是静态的,而你的是非静态的。被重写的方法在People类中,代码如下:

“全栈2019”Java第四十八章:重写方法Override

总结

  • 子类中具有相同签名(方法名,加上其参数的数量和类型)和返回类型的实例方法作为父类中的实例方法时会重写父类的方法。
  • 重写方法时,请使用@Override注解来指示编译器您要重写父类中的方法。
  • 子类重写方法的能力允许类从“足够接近”的父类继承行为,然后根据需要修改行为。重写方法具有相同的名称,参数的数量和类型和返回类型作为它重写的方法。
  • 重写方法还可以返回由重写方法返回的类型的子类型。此子类型称为协变返回类型。
  • 如果子类定义的类方法与父类中的类方法具有相同的签名,则子类中的方法会隐藏父类中的方法。
  • 隐藏类方法和重写实例方法之间的区别具有重要意义:(一)被调用的重写实例方法的版本是子类中的版本。(二)被调用的隐藏静态方法的版本取决于它是从超类还是从子类调用的。
  • 子类重写方法的访问修饰符只能比父类访问修饰符权限大,不能小。 例如,父类中的受保护实例方法可以在子类中公开,但不能是私有的。
  • 如果尝试将父类中的实例方法更改为子类中的静态方法,则会出现编译时错误,反之亦然。

至此,Java中重写方法@Override相关内容讲解先告一段落,更多内容请持续关注。

答疑

如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。

上一章

“全栈2019”Java第四十七章:继承与方法

下一章

“全栈2019”Java第四十九章:重载与重写对比详解

学习小组

加入同步学习小组,共同交流与进步。

  • 方式一:关注头条号Gorhaf,私信“Java学习小组”。
  • 方式二:关注公众号Gorhaf,回复“Java学习小组”。

全栈工程师学习计划

关注我们,加入“全栈工程师学习计划”。

“全栈2019”Java第四十八章:重写方法Override

版权声明

原创不易,未经允许不得转载!