菜鸟Java面向对象 2. Java 重写(Override)与重载(Overload)

Java 重写(Override)与重载(Overload)

Java 重写与重载

  • Java 重写(Override)与重载(Overload)
    • 1. 重写(Override)
      • 1. 概念解释:
      • 2. 好处说明
      • 3. 异常规则处理
    • 2. 方法的重写规则
    • 3. Super 关键字的使用
    • 4. 重载(Overload)
      • **重载规则:**
      • 实例
    • 5. 重写与重载之间的区别
    • 总结

1. 重写(Override)

1. 概念解释:

重写(Override)是指子类定义了一个与其父类中具有相同名称、参数列表和返回类型的方法,并且子类方法的实现覆盖了父类方法的实现。
即外壳不变,核心重写!
(或接口不变,内核更新)

2. 好处说明

重写的好处在于子类可以根据需要,定义特定于自己的行为
也就是说子类能够根据需要实现父类的方法
这样,在使用子类对象调用该方法时,将执行子类中的方法而不是父类中的方法

3. 异常规则处理

重写方法不能抛出新的检查异常或者比被重写方法申明 更加宽泛的异常。(编译上可以,逻辑上不允许)

例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,抛出 IOException 异常或者 IOException 的子类异常。


当一个方法在父类中声明了检查异常(checked exception),例如 IOException,这意味着在调用这个方法时,调用方必须要么使用try-catch块来处理异常,要么将异常通过throws子句传播到更高层次的调用者。

现在考虑一个情况,如果子类重写了父类的方法,并且在重写的方法中抛出了一个比父类方法申明的异常更加宽泛的异常,比如 Exception,这将会引起问题。因为调用方可能依赖于父类方法声明的异常类型来进行异常处理。如果子类方法抛出的异常类型更加宽泛,那么调用方可能会收到意料之外的异常,这可能会破坏代码的健壮性和可维护性。

举个例子来说明:

// 父类
class Parent {// 父类方法声明了 IOException 异常void doSomething() throws IOException {// 父类方法可能会抛出 IOException 异常}
}// 子类
class Child extends Parent {// 子类重写父类方法,但是抛出了 Exception 异常,比父类宽泛@Overridevoid doSomething() throws Exception {// 子类方法实现}
}// 调用方
public class Main {public static void main(String[] args) {Parent obj = new Child();try {obj.doSomething(); // 子类方法抛出了 Exception 异常} catch (IOException e) {// 调用方期待捕获的是 IOException 异常,但实际收到了更加宽泛的 Exception 异常e.printStackTrace();}}
}

在这个例子中,调用方期待捕获的是 IOException 异常,但是由于子类方法抛出了更加宽泛的 Exception 异常,导致调用方收到了意料之外的异常。这可能会破坏代码的健壮性和可维护性。

因此,Java的设计约定是,在重写父类方法时,子类方法的异常声明不能比父类方法的异常声明更加宽泛,只能抛出父类方法声明的异常类型或其子类异常。


在面向对象原则里,重写意味着可以重写任何现有方法。实例如下:

//TestDog.java 文件代码:
class Animal{public void move(){ // 定义动物类的移动方法System.out.println("动物可以移动"); // 输出动物可以移动}
}class Dog extends Animal{ // Dog 类继承自 Animal 类public void move(){ // 重写了父类的 move 方法System.out.println("狗可以跑和走"); // 输出狗可以跑和走}
}public class TestDog{public static void main(String args[]){Animal a = new Animal(); // 创建 Animal 对象Animal b = new Dog(); // 创建 Dog 对象,但是引用类型是 Animala.move(); // 调用 Animal 类的 move 方法,输出动物可以移动b.move(); // 调用 Dog 类的 move 方法,输出狗可以跑和走}
}

以上实例编译运行结果如下:

动物可以移动
狗可以跑和走

在上面的例子中可以看到,尽管 b 属于 Animal 类型,但是它运行的是 Dog 类的 move方法。

这是由于在编译阶段,只是检查参数的引用类型。

然而在运行时,Java 虚拟机(JVM)指定对象的类型并且运行该对象的方法。

因此在上面的例子中,之所以能编译成功,是因为 Animal 类中存在 move 方法,然而运行时,运行的是特定对象的方法。

思考以下例子:

//TestDog.java 文件代码:
class Animal{public void move(){ // 定义动物类的移动方法System.out.println("动物可以移动"); // 输出动物可以移动}
}class Dog extends Animal{ // Dog 类继承自 Animal 类public void move(){ // 重写了父类的 move 方法System.out.println("狗可以跑和走"); // 输出狗可以跑和走}public void bark(){ // 定义狗类的吠叫方法System.out.println("狗可以吠叫"); // 输出狗可以吠叫}
}public class TestDog{public static void main(String args[]){Animal a = new Animal(); // 创建 Animal 对象Animal b = new Dog(); // 创建 Dog 对象,但是引用类型是 Animala.move(); // 调用 Animal 类的 move 方法,输出动物可以移动b.move(); // 调用 Dog 类的 move 方法,输出狗可以跑和走b.bark(); // 调用 Dog 类的 bark 方法,输出狗可以吠叫}
}

以上实例编译运行结果如下:

TestDog.java:30: cannot find symbol
symbol  : method bark()
location: class Animalb.bark();^

该程序将抛出一个编译错误,因为b的引用类型Animal没有bark方法。


problem: The method bark() is undefined for the type Animalat Animal.TestDog.main(TestDog.java:27)

这个错误说明了在 Animal 类中没有定义名为 bark 的方法,而在主方法中却尝试调用了这个方法。让我们来修复这个问题:

class Animal{public void move(){ // 定义动物类的移动方法System.out.println("动物可以移动"); // 输出动物可以移动}
}class Dog extends Animal{ // Dog 类继承自 Animal 类public void move(){ // 重写了父类的 move 方法System.out.println("狗可以跑和走"); // 输出狗可以跑和走}public void bark(){ // 定义狗类的吠叫方法System.out.println("狗可以吠叫"); // 输出狗可以吠叫}
}public class TestDog{public static void main(String args[]){Animal a = new Animal(); // 创建 Animal 对象Animal b = new Dog(); // 创建 Dog 对象,但是引用类型是 Animala.move(); // 调用 Animal 类的 move 方法,输出动物可以移动b.move(); // 调用 Dog 类的 move 方法,输出狗可以跑和走if (b instanceof Dog) { // 检查 b 是否为 Dog 类的实例((Dog)b).bark(); // 如果是 Dog 类的实例,强制转换为 Dog 类并调用 bark 方法}}
}

就是把

b.bark(); // 调用 Dog 类的 bark 方法,输出狗可以吠叫

修改成

if (b instanceof Dog) { // 检查 b 是否为 Dog 类的实例((Dog)b).bark(); // 如果是 Dog 类的实例,强制转换为 Dog 类并调用 bark 方法}

在这个修改后的版本中,我们在调用 b.bark() 之前使用了 instanceof 运算符来检查 b 是否为 Dog 类的实例。如果是,则进行强制类型转换并调用 bark 方法。这样就可以避免在 Animal 类中调用 bark 方法而产生编译错误。


2. 方法的重写规则

  1. 参数列表必须相同: 重写方法的参数列表必须与被重写方法完全相同,包括参数的类型、顺序和数量。

  2. 返回类型可以不同: 重写方法的返回类型可以与被重写方法不同,但是必须是被重写方法返回值的派生类。在Java 5及更早版本中,返回类型必须相同。在Java 7及更高版本中,可以不同。

  3. 访问权限不能低于父类: 重写方法的访问权限不能比父类中被重写方法的访问权限更低,因为子类不能降低父类的访问权限。。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。

  4. 只能重写父类的成员方法: 只有父类中的成员方法才能被子类重写,不能重写父类的成员变量、静态方法等。

  5. final 方法不能被重写: 被声明为 final 的方法不能被子类重写,因为 final 方法是不可改变的。

  6. static 方法不能被重写: 被声明为 static 的方法不能被子类重写,但是可以被再次声明。

  7. 包内和包外的限制: 如果子类和父类在同一个包中,子类可以重写父类的所有方法,除了被声明为 private 和 final 的方法。如果不在同一个包中,子类只能重写父类声明为 public 和 protected 的非 final 方法。

  8. 异常处理规则: 重写的方法可以抛出任何非强制异常,但是不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常。

  9. 构造方法不能被重写: 构造方法是用来创建对象的特殊方法,不能被子类重写。

  10. 不能继承的类不能重写: 如果一个类不能被继承(比如被声明为 final),那么它的方法也不能被重写。

这些规则确保了方法重写的合理性和一致性,遵循这些规则可以避免出现一些常见的错误和不一致性。


3. Super 关键字的使用

当需要在子类中调用父类的被重写方法时,要使用 super 关键字。

//TestDog.java 文件代码:
class Animal{public void move(){ // 定义动物类的移动方法System.out.println("动物可以移动"); // 输出动物可以移动}
}class Dog extends Animal{ // Dog 类继承自 Animal 类public void move(){ // 重写了父类的 move 方法super.move(); // 调用父类的 move 方法System.out.println("狗可以跑和走"); // 输出狗可以跑和走}
}public class TestDog{public static void main(String args[]){Animal b = new Dog(); // 创建 Dog 对象,但是引用类型是 Animalb.move(); // 调用 Dog 类的 move 方法,输出动物可以移动和狗可以跑和走}
}

以上实例编译运行结果如下:

动物可以移动
狗可以跑和走

4. 重载(Overload)

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

最常用的地方就是构造器的重载。

重载规则:

  • 被重载的方法必须改变参数列表(参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

实例

public class Overloading {public int test(){ // 定义一个返回类型为 int 的 test 方法,无参数System.out.println("test1"); // 输出 test1return 1; // 返回值为 1}public void test(int a){ // 定义一个无返回值的 test 方法,参数为一个 int 类型的变量 aSystem.out.println("test2"); // 输出 test2}   // 以下两个方法参数类型顺序不同public String test(int a, String s){ // 定义一个返回类型为 String 的 test 方法,参数为一个 int 类型的变量 a 和一个 String 类型的变量 sSystem.out.println("test3"); // 输出 test3return "returntest3"; // 返回值为 "returntest3"}   public String test(String s, int a){ // 定义一个返回类型为 String 的 test 方法,参数为一个 String 类型的变量 s 和一个 int 类型的变量 aSystem.out.println("test4"); // 输出 test4return "returntest4"; // 返回值为 "returntest4"}   public static void main(String[] args){Overloading o = new Overloading(); // 创建 Overloading 对象System.out.println(o.test()); // 调用 test 方法,输出 test1,然后打印返回值 1o.test(1); // 调用带有一个 int 参数的 test 方法,输出 test2System.out.println(o.test(1, "test3")); // 调用带有一个 int 和一个 String 参数的 test 方法,输出 test3,然后打印返回值 "returntest3"System.out.println(o.test("test4", 1)); // 调用带有一个 String 和一个 int 参数的 test 方法,输出 test4,然后打印返回值 "returntest4"}
}

5. 重写与重载之间的区别

区别点重载方法重写方法
参数列表必须修改一定不能修改
返回类型可以修改一定不能修改
异常可以修改可以减少或删除,一定不能抛出新的或者更广的异常
访问可以修改一定不能做更严格的限制(可以降低限制)

总结

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

  • (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
  • (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
  • (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/2337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是手机运营商三要素验证API接口

手机运营商三要素验证API接口又叫手机运营商三要素核验API接口,指的是输入姓名、身份证号码及手机号,通过运营商数据库实时校验此三项是否匹配。手机运营商三要素核验API接口广泛用于实名注册、风控审核等场景,如电商、直播、游戏、金融等。接…

Leetcode刷题之链表小结(1)|92反转链表|206反转链表

TOC 小结 1. 如何反转某一个节点的指向? 206反转链表(简单)的递归解法——该方法的理念是: 若节点k1到节点m已经被反转,而我们当前处于k位置,那么我们希望k1指向k, 体现在以下代码的head->next->next head;这一句,可以记做一种常用的反转单个…

AI+招聘,激活企业的「新质生产力」

两会以来,「新质生产力」成为热词。而所谓的新质生产力,是创新起主导作用,摆脱传统经济增长方式、生产力发展路径,具有高科技、高效能、高质量特征,符合新发展理念的先进生产力质态。新质之「新」,很重要的…

wandb注册 wandb: ERROR api_key

wandb: ERROR api_key not configured (no-tty). call wandb.login(key[your_api_key]) Traceback (most recent call last): 背景 使用yolov8训练时 在pycharm中出现wandb账号未注册错误 Transferred 355/355 items from pretrained weights TensorBoard: Start with tensor…

平衡二叉树(AVLTree)

AVLTree 1、树的分类2、平衡二叉树2.1、构建一个平衡二叉树2.2、删除节点2.3、搜索方式2.3.1、广度优先搜索(BFS)2.3.2、深度优先搜索(DFS) 1、树的分类 树形结构是编程当中特别常见的一种数据结构。比如电脑中的文件管理系统就大…

(超级详细)JAVA之Stream流分析-------持续更新喔!!!

学习目标: 掌握 Java Stream流的相关api 掌握 Java Stream流的基本实现 掌握 java Stream流的使用场景 代码已经整理上传到了gitee中,有需要的小伙伴可以取查看一下源码点个小心心喔 大家也可以帮我提交一点案例喔!!!&…

【QT进阶】Qt Web混合编程之使用ECharts显示各类折线图等

往期回顾 【QT进阶】Qt Web混合编程之QWebEngineView基本用法-CSDN博客 【QT进阶】Qt Web混合编程之CMake VS2019编译并使用QCefView(图文并茂超详细版本)-CSDN博客【QT进阶】Qt Web混合编程之html、 js的简单交互-CSDN博客 【QT进阶】Qt Web混合编程之使…

【MATLAB源码-第196期】基于matlab的A*融合DWA算法栅格路径规划仿真,画出路径图、姿态角度以及线角速度。

操作环境: MATLAB 2022a 1、算法描述 A算法与DWA算法的融合是一个高效的路径规划策略,这种策略将A算法的全局路径规划能力与DWA算法的局部避障能力结合起来,以期达到更快、更安全的导航效果。以下是对这种融合策略的详细描述。 一、基本概…

Linux thermal框架介绍

RK3568温控 cat /sys/class/thermal/thermal_zone0/temp cat /sys/class/thermal/thermal_zone1/temp cat /sys/class/thermal/cooling_device0/cur_state cat /sys/class/thermal/cooling_device1/cur_state cat /sys/class/thermal/cooling_device2/cur_state thermal_zone…

信息打点--公众号服务

微信公众号 获取微信公众号的途径https://weixin.sogou.com/ 微信公众号没有第三方服务 Github监控 人员&域名&邮箱 eg:xxx.cn password in:file https://gitee.com/ https://github.com/ https://www.huzhan.com/ 资源搜索 in:name test 仓库标题搜索含有…

ASP.NET教务管理平台-权限及公共模块设计与开发

摘 要 随着教育改革的不断深化,高等院校的建设与发展对国民整体素质的提高起着越来越重要的作用,建立一套能够适应这些改变的行政管理方案也就显得尤为重要。对于教务处来说,将信息技术用于校务管理中便是迫切的要求。 教务系统中的用户…

产品规划|如何从0到1规划设计一款产品?

我们要如何从0到1规划设计一款产品?在前期工作我们需要做什么呢?下面这篇文章就是关于此的相关内容,大家一起往下看多多了解了解吧! 一、什么是产品规划? 产品规划是一种策略,它设定了产品的价值和目标,并确定实施方案以实现这些目标。它考虑了产品的整个生命周期,基于…

22长安杯电子取证复现(检材一,二)

检材一 先用VC容器挂载,拿到完整的检材 从检材一入手,火眼创建案件,打开检材一 1.检材1的SHA256值为 计算SHA256值,直接用火眼计算哈希计算 9E48BB2CAE5C1D93BAF572E3646D2ECD26080B70413DC7DC4131F88289F49E34 2.分析检材1&am…

dremio支持设置

Dremio 支持提供可用于诊断目的的设置。这些设置通过 Dremio UI:设置>支持启用(或禁用) 使用 Client Tools 可以配置当用户查看数据集中的数据时,Dremio 项目的工具栏上显示哪些客户端应用程序按钮。用户可以通过单击相应的工具…

海外媒体广告投放 - 大舍传媒助力企业迈向新台阶,实现精准投放

一、为何选择海外媒体广告投放 随着全球化进程的不断推进,越来越多的企业开始将目光投向国际市场。海外媒体广告投放作为一种有效的宣传手段,可以帮助企业在全球范围内提高品牌知名度和影响力,吸引潜在客户,促进产品销售。 二、…

12、【装饰器模式】动态地为对象添加新功能

你好,我是程序员雪球。 今天我们来聊聊 23 种设计模式中,一种常见的结构型模式,装饰器模式。聊聊它的设计思想、实现原理,应用场景,以及如何使用。 装饰器模式(Decorator Pattern)是一种结构型…

使用d3.js画一个BoxPlot

Box Plot 在画Box Plot之前,先来了解下Box Plot是什么? 箱线图(Box Plot)也称盒须图、盒式图或箱型图,是一种用于展示数据分布特征的统计图表。 它由以下几个部分组成: 箱子:表示数据的四分…

ruoyi element-ui 实现拖拉调整图片顺序

ruoyi element-ui 实现拖拉调整图片顺序 安装sortablejs https://sortablejs.com/npm 安装sortablejs npm install sortablejs --save相关options var sortable new Sortable(el, {group: "name", // or { name: "...", pull: [true, false, clone, …

甘特图:如何制定一个有效的产品运营规划?

做好一个产品的运营规划是一个复杂且系统的过程,涉及多个方面和阶段。以下是一些关键步骤和考虑因素,帮助你制定一个有效的产品运营规划: 1、明确产品定位和目标用户: 确定产品的核心功能、特点和优势,明确产品在市…

python自动生成SQL语句自动化

👽发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Python自动生成SQL语句自动化 在数据处理和管理中,SQL(Structured …