【Java基础】为什么不支持多重继承?方法重载和方法重写之间区别、Exception 和 Error 区别?

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
🌱🌱个人主页:奋斗的明志
🌱🌱所属专栏:Java基础面经

📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。

在这里插入图片描述

Java 基础

  • 一、为什么 Java 不支持多重继承?
    • 1、解释
    • 2、多继承不行,为什么接口多实现可以呢?
      • 2.1 Java JDK8 之前
      • 2.1 Java JDK8+
    • 3、总结
  • 二、Java 中 方法重载和方法重写之间的区别是什么?
    • 1、区别
    • 2、重载注意点
    • 2、重写注意点
  • 三、Java 中 Exception 和 Error 有什么区别?
    • 1、Exception
    • 2、Error
    • 3、图示各层关系
    • 4、异常处理注意点
      • 4.1 尽量不要捕获类似 Exception 这样通用的异常,而应该捕获特定的异常
      • 4.2 不要“吞”了异常
      • 4.3 不要延迟处理异常
      • 4.4 只在需要try-catch的地方try-catch,try-catch的范围能小则小
      • 4.5 不要通过异常来控制程序流程
      • 4.6 不要在finally代码块中处理返回值或者直接return

一、为什么 Java 不支持多重继承?

1、解释

主要是因为多继承会产生 菱形继承(也叫钻石继承)问题,Jva之父就是吸取C++他们的教训,因此不支持多继承。
所谓的菱形继承很好理解,我们来看下这个图:

在这里插入图片描述

是不是看起来很像一个菱形,BC继承了A,然后D继承了BC,假设此时要调用D内定义在A的方法,因为B和C都有不同的实现
此时就会出现歧义,不知道应该调用哪个了。

// 假设允许多继承(伪代码)
class A { void foo() { System.out.println("A"); } }
class B { void foo() { System.out.println("B"); } }
class C extends A, B {} // 错误:C 中的 foo() 是继承 A 还是 B?

2、多继承不行,为什么接口多实现可以呢?

接口和抽象类不同,接口里的方法都是抽象的(在Java 8之前),没有具体的实现。
所以当一个类实现多个接口时,即使这些接口有相同的方法签名,类只需要提供一个具体的实现,这样就避免了方法冲突的问题。因为接口本身没有实现,不会有多个实现带来的歧义。即使两个接口有相同的方法,实现类只需要实现一次这个方法,这样就不会有问题。

Java 8之后接口可以有默认方法,这时候如果有多个接口有相同的默认方法,实现类必须重写这个方法,否则编译器会报错。
这时候就需要在实现类中明确指定使用哪个接口的默认方法,或者自己重新实现。这可能也是允许接口多实现的一个调整,但核心还是因为接口的默认方法需要显式处理冲突,而类继承的结构性问题无法解决。

2.1 Java JDK8 之前

interface X { void foo(); }
interface Y { void foo(); }class Z implements X, Y {@Overridepublic void foo() { System.out.println("Z 统一实现 X 和 Y 的 foo()");}
}

2.1 Java JDK8+

  • 这种强制重写机制将冲突的解决权交给开发者,确保逻辑明确。
interface X { default void foo() { System.out.println("X"); } }
interface Y { default void foo() { System.out.println("Y"); } }class Z implements X, Y {@Overridepublic void foo() {X.super.foo(); // 显式选择调用 X 的默认实现// 或 Y.super.foo(); 或自定义逻辑}
}

3、总结

Java 通过禁止类的多继承避免了菱形问题和状态冲突,而接口的多实现通过以下机制保证安全:

  • 接口方法由实现类统一实现(消除方法歧义)。

  • 默认方法冲突需显式解决(开发者控制逻辑)。

  • 接口不涉及状态管理(避免字段冲突)。

这种设计在保证语言简洁性的同时,提供了高度的灵活性,符合“单一继承,多重接口”的面向对象设计原则。

二、Java 中 方法重载和方法重写之间的区别是什么?

1、区别

  • 方法重载(Overloading):在同一个类中,允许有多个同名方法,只要它们的参数列表不同(参数个数、类型或顺序)。主要关注方法的签名变化,适用于在同一类中定义不同场景下的行为

  • 方法重写(Overriding):子类在继承父类时,可以重写父类的某个方法(参数列表、方法名必须相同),从而为该方法提供新的实现。主要关注继承关系,用于子类改变父类的方法实现,实现运行时多态性

  • 区别主要如下:

区别重载重写
发生的场所在同一个类中在继承关系的子类和父类之间
参数列表必须不同(参数的数量、类型或顺序不同)必须相同,不能改变参数列表
返回类型可以不同必须与父类方法的返回类型相同,或者是父类返回类型的子类(协变返回类型)
访问修饰符不受访问修饰符影响子类方法的访问修饰符不能比父类更严格,通常是相同或更宽泛
静态和非静态方法可以是静态方法或非静态方法只能重写非静态方法,静态方法不能被重写(静态方法可以被隐藏)
异常处理方法的异常处理可以不同子类的异常不能抛出比父类更多的异常(可以抛出更少的或相同类型的异常)

2、重载注意点

重载中提到的方法同名 但参数列表不同(参数个数、类型或顺序),这里要注意和返回值没有关系,方法的签名仅是名字和参数列表不包括返回值

重载通常用于提供同一操作的不同实现,例如构造函数的重载、不同类型输入的处理等。

  • 代码实现:
public class A{// 重载方法:参数数量不同public void print(int a) {System.out.println("Printing int: " + a);}// 重载方法:参数类型不同public void print(String a) {System.out.println("Printing String: " + a);}// 重载方法:参数类型和数量不同public void print(int a, int b) {System.out.println("Printing two ints: " + a + ", " + b);}
}

2、重写注意点

在重写时,子类方法不能使用比父类更严格的访问级别
例如,父类的方法是 protected,子类不能将其修改为 private,但可以改为public
子类方法抛出的异常必须与父类一致,或者是其父类异常的子类

重写通常用于在子类中提供父类方法的具体实现,以实现运行时多态性。例如,子类对父类方法进行扩展或修改以适应特定需求。

  • 代码实现:
class A{public void display() {System.out.println("Parent display");}
}class B extends A{@Overridepublic void display() {System.out.println("Child display");}
}public class Test{public static void main(String[] args) {A a = new B();a.display(); // 输出 "Child display"}
}
  • 还有一个@Override注解,在重写方法时使用@Override注解,编译器可以帮助检查是否正确实现了重写,以防误操作。

三、Java 中 Exception 和 Error 有什么区别?

ExceptionError 都是 Throwable 类的子类(在Java代码中,只有继承了 Throwable 类的实例才可以被 throw 或者被 catch
它们表示在程序运行时发生的异常或者错误情况

总结:Exception 表示可以被处理的程序异常,Error 表示系统级的不可恢复错误

1、Exception

Exception : 是程序中可以处理的异常情况,表示程序逻辑或外部环境中的问题,可以通过代码进行恢复或处理。
常见子类有:IOExceptionSQLExceptionNullPointerExceptionIndexOutofBoundsException等。
Exception 又分为 Checked Exception(编译期异常)Unchecked Exception(运行时异常)
Checked Exception : 在编译时必须显式处理(如使用try-catch块或通过throws声明抛出)。如IOException
Unchecked Exception : 运行时异常,不需要显式捕获。常见的如 NullPointerExceptionIllegalArgumentException 等,继承自 RuntimeException

2、Error

Error 表示严重的错误,通常是 JVM 层次内系统级的、无法预料的错误,程序无法通过代码进行处理或恢复。例如内存耗尽(OutofMemoryError)栈溢出(Stackoverf1 OwError)。Error 不应该被程序捕获或处理,因为一般出现这种错误时程序无法继续运行。

3、图示各层关系

在这里插入图片描述

比如用户编写一个程序,如果文件没找到,会抛出 FileNotFoundException,属于编译异常,必须处理。而如果程序递归太深导致栈溢出,会抛出 StackOverflowError,属于 Error,程序一般无法处理。

4、异常处理注意点

4.1 尽量不要捕获类似 Exception 这样通用的异常,而应该捕获特定的异常

软件工程是一门协作的艺术,在日常的开发中我们有义务使自己的代码能更直观、清晰地表达出我们想要表达的信息。
但是如果你什么异常都用了 Exception ,那别的开发同事就不能一眼得知这段代码实际想要捕获的异常,并且这样的代码也会捕获到可能你希望它抛出而不希望捕获的异常。

4.2 不要“吞”了异常

如果我们捕获了异常,不把异常抛出,或者没有写到日志里,那会出现什么情况?线上除了bug莫名其妙的没有任何的信息,你都不知道哪里出错以及出错的原因。
这可能会让一个简单的bug变得难以诊断,而且有些同学比较喜欢用 catch之后 e.printStackTrace(),在我们产品中通常不推荐用这种方法,一般情况下这样是没有问题的但是这个方法输出的是个标准错误流。
比如是在分布式系统中,发生异常但是找不到 stacktrace
所以最好是输入到日志里,我们产品可以自定义一定的格式,将详细的信息输入到日志系统中,适合清晰高效的排查错误。

4.3 不要延迟处理异常

比如有个方法,参数是个 name,函数内部调了别的好几个方法,其实你的 name 传的是 null 值,但是你没有在进入这个方法或者这个方法一开始就处理这个情况,而是在你调了别的好几个方法然后爆出这个空指针。这样的话明明你的出错堆栈信息只需要抛出一点点信息就能定位到这个错误所在的地方,经过了好多方法之后可能就是一坨堆栈信息。

4.4 只在需要try-catch的地方try-catch,try-catch的范围能小则小

只要必要的代码段使用try-catch,不要不分青红皂白try住一坨代码,因为try-catch中的代码会影响JVM对代码的优化,例如重排序。

4.5 不要通过异常来控制程序流程

一些可以用 if/lse 的条件语句来判断 例如 null 值等,就不要用异常,异常肯定是比一些条件语句低效的,有CPU分支预测的优化等。
而且每实例化一个 Exception 都会对栈进行快照,相对而言这是一个比较重的操作,如果数量过多开销就不能被忽略了。

4.6 不要在finally代码块中处理返回值或者直接return

finallyreturn 或者处理返回值会让发生很诡异的事情,比如覆盖了try中的return,或者屏蔽的异常。

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

c++ haru生成pdf输出饼图

#define PI 3.14159265358979323846 // 绘制饼图的函数 void draw_pie_chart(HPDF_Doc pdf, HPDF_Page page, float *data, int data_count, float x, float y, float radius) { float total 0; int i; // 计算数据总和 for (i 0; i < data_count; i) { tot…

Linux 创建进程 fork()、vfork() 与进程管理

Linux 创建进程 fork、vfork、进程管理 一、Linux的0号、1号、2号进程二、Linux的进程标识三、fork() 函数1、基本概念2、函数特点3、用法以及应用场景&#xff08;1&#xff09;父子进程执行不同的代码&#xff08;2&#xff09;进程执行另一个程序 4、工作原理 四、vfork() 函…

【漫话机器学习系列】082.岭回归(或脊回归)中的α值(alpha in ridge regression)

岭回归&#xff08;Ridge Regression&#xff09;中的 α 值 岭回归&#xff08;Ridge Regression&#xff09;是一种 带有 L2​ 正则化 的线性回归方法&#xff0c;用于处理多重共线性&#xff08;Multicollinearity&#xff09;问题&#xff0c;提高模型的泛化能力。其中&am…

电脑重启后vscode快捷方式失效,找不到code.exe

今天打开电脑发现vscode的快捷方式失效了&#xff0c;提示code.exe被删除或移动。 解决方法 查看vscode安装目录&#xff0c;发现多了一个_文件夹&#xff0c;包括code.exe在内的其他文件都被移动到了这个文件夹下。 将里面内容都移动到microsoft vs code文件夹下&#xff0c…

[权限提升] Linux 提权 维持 — 系统错误配置提权 - Sudo 滥用提权

关注这个专栏的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;Sudo 滥用提权原理 Sudo 是一个 Linux 系统管理命令&#xff0c;它允许系统管理员授予普通用户以指定身份执行指定命令的权限。该命令不仅减少了 Root 用户的登录时间和管理时…

激活函数篇 04 —— softmax函数

将模型的输出转换为概率分布&#xff0c;使得模型能够输出每个类别的概率值。 Softmax ( a i ) e a i ∑ j 1 n e a j \text{Softmax}(a_i)\frac{e^{a_i}}{\sum_{j1}^n e^{a_j}} Softmax(ai​)∑j1n​eaj​eai​​ 其中&#xff0c; a i a_i ai​ 是输入向量中的第 i i i 个…

【韩顺平linux】部分上课笔记整理

整理一下一些韩顺平老师上课时候的笔记 课程&#xff1a;【小白入门 通俗易懂】韩顺平 一周学会Linux linux环境&#xff1a;使用阿里云服务器 笔记参考 &#xff1a; [学习笔记]2021韩顺平一周学会Linux 一、自定义函数 基本语法 应用实例&#xff1a; 计算两个参数的和…

redis底层数据结构——简单动态字符串

文章目录 概述什么时候用C里面的字符串什么时候使用SDS使用场景 SDS定义SDS与C语言的字符串差异常数时间复杂度获取字符串长度杜绝缓冲区溢出减少修改字符串时带来的内存重分配次数1.空间预分配2.情性空间释放 二进制安全兼容部分C字符串函数总结 开始讲述动态字符串前我们先问…

使用 POI-TL 和 JFreeChart 动态生成 Word 报告

文章目录 前言一、需求背景二、方案分析三、 POI-TL JFreeChart 实现3.1 Maven 依赖3.3 word模板设置3.2 实现代码 踩坑 前言 在开发过程中&#xff0c;我们经常需要生成包含动态数据和图表的 Word 报告。本文将介绍如何结合 POI-TL 和 JFreeChart&#xff0c;实现动态生成 W…

VLLM历次会议(2024.1)

Azure官宣支持VLLM VLLM支持AMD芯片 支持Mixtral MoE&#xff0c;支持DeepSeek MoE 性能优化 &#xff08;以下4招&#xff0c;总共将吞吐量提升50%&#xff0c;延迟降低40%&#xff09; 1. PageAttention V2 &#xff08;同一个Q&#xff0c;和不同的KV的计算&#xff0c…

第一财经对话东土科技 | 探索工业科技新边界

当前以ChatGPT、Sora等为代表的生成式人工智能快速发展&#xff0c;越来越多面向垂直场景的行业大模型涌现出来&#xff0c;并成为推动制造业智能化改造与数字化转型、加快推进新型工业化&#xff0c;进而培育发展新质生产力的新引擎。 在垂类场景的应用落地&#xff0c;是AI发…

RabbitMq入门

1.MQ的相关概念 1.1 什么是MQ MQ(message queue)&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO先入先出&#xff0c;只不过队列中存放的内容是message而已&#xff0c;还是一种跨进程的通信机制&#xff0c;用于上下游传递消息。在互联网架构中&#xf…

【报错解决】MySQL报错:sql_mode=only_full_group_by

文章目录 报错信息 DataGrip 报错还原Navicat 报错还原 报错原因解决方案 查看当前 sql mode方案一&#xff1a;临时解决方案二&#xff1a;永久解决方案三&#xff1a;使用 any_value() 或 group_concat()方案四&#xff1a;调整实现思路&#xff0c;避开 GROUP BY 使用 我…

postgresql 游标(cursor)的使用

概述 PostgreSQL游标可以封装查询并对其中每一行记录进行单独处理。当我们想对大量结果集进行分批处理时可以使用游标&#xff0c;因为一次性处理可能造成内存溢出。 另外我们可以定义函数返回游标类型变量&#xff0c;这是函数返回大数据集的有效方式&#xff0c;函数调用者…

十二、Docker Compose 部署 SpringCloudAlibaba 微服务

一、部署基础服务 0、项目部署结构 项目目录结构如下: /home/zhzl_hebei/ ├── docker-compose.yml └── geochance-auth/└── Dockerfile└── geochance-auth.jar └── geochance-system/└── Dockerfile└── geochance-system.jar └── geochance-gateway/…

java项目之金华学校社团管理系统源码(ssm+mysql)

项目简介 金华学校社团管理系统实现了以下功能&#xff1a; 金华学校社团管理系统的主要使用者管理员对系统用户、公告信息进行管理。对社团信息进行管理&#xff0c;审核报名&#xff0c;统计社团报名结果等。学生维护个人信息&#xff0c;查看本校的社团信息&#xff0c;对…

deepseek+kimi自动生成ppt

打开deepseek官网&#xff0c;输入详细的需求&#xff0c;让他生成个ppt 接着deepseek开始思考生成了 接着复制生成了的内容 打开kimi粘贴刚才deepseek生成的内容 可以一键生成啦&#xff0c;下载编辑使用吧

Shapefile格式文件解析和显示

Java实现GIS SHP文件格式的解析和显示&#xff0c;JDK19下编译&#xff0c;awt图形系统显示。 SHP文件对应的属性存储在DBF格式数据库中&#xff0c;解析见&#xff1a;DBASE DBF数据库文件解析_数据库文件在线解析-CSDN博客 解析SHP文件代码&#xff1a; public static Shap…

Golang 并发机制-7:sync.Once实战应用指南

Go的并发模型是其突出的特性之一&#xff0c;但强大的功能也带来了巨大的责任。sync.Once是由Go的sync包提供的同步原语。它的目的是确保一段代码只执行一次&#xff0c;而不管有多少协程试图执行它。这听起来可能很简单&#xff0c;但它改变了并发环境中管理一次性操作的规则。…

【DeepSeek × Postman】请求回复

新建一个集合 在 Postman 中创建一个测试集合 DeepSeek API Test&#xff0c;并创建一个关联的测试环境 DeepSeek API Env&#xff0c;同时定义两个变量 base_url 和 api_key 的步骤如下&#xff1a; 1. 创建测试集合 DeepSeek API Test 打开 Postman。点击左侧导航栏中的 Co…