Java 核心技术面试精讲
杨晓峰
前 Oracle 首席工程师
125942 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 44 讲
Java 核心技术面试精讲
15
15
1.0x
00:00/00:00
登录|注册

第2讲 | Exception和Error有什么区别?

不检查异常(运行时异常)
可检查异常
Error
Exception
不同编程范式对异常处理的影响
实例化异常的栈快照开销
try-catch代码段的性能开销
自定义异常的考虑
Throw early, catch late原则
不生吞异常
不捕获通用异常
Throwable
异常处理的影响因素
异常处理的性能开销
异常处理的最佳实践
Exception和Error
Java异常处理机制

该思维导图由 AI 生成,仅供参考

世界上存在永远不会出错的程序吗?也许这只会出现在程序员的梦中。随着编程语言和软件的诞生,异常情况就如影随形地纠缠着我们,只有正确处理好意外情况,才能保证程序的可靠性。
Java 语言在设计之初就提供了相对完善的异常处理机制,这也是 Java 得以大行其道的原因之一,因为这种机制大大降低了编写和维护可靠程序的门槛。如今,异常处理机制已经成为现代编程语言的标配。
今天我要问你的问题是,请对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别?

典型回答

Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于非正常的、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如 OutOfMemoryError 之类,都是 Error 的子类。
Exception 又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。前面我介绍的不可查的 Error,是 Throwable 不是 Exception。
不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。

考点分析

分析 Exception 和 Error 的区别,是从概念角度考察了 Java 处理机制。总的来说,还处于理解的层面,面试者只要阐述清楚就好了。
我们在日常编程中,如何处理好异常是比较考验功底的,我觉得需要掌握两个方面。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java异常处理机制是Java编程中的重要组成部分。异常和错误都是继承了Throwable类的基本组成类型,Exception是程序正常运行中可以预料的意外情况,需要被捕获和处理;而Error是在正常情况下不太可能出现的情况,大部分会导致程序处于不可恢复状态。在日常编程中,理解Throwable、Exception、Error的设计和分类,以及掌握Java语言中操作Throwable的元素和实践是非常重要的。文章还提到了异常处理的最佳实践,如避免捕获通用异常、不生吞异常、遵循“Throw early, catch late”原则等。此外,文章还探讨了Java异常处理机制的性能开销和不同编程范式对异常处理策略的影响。总的来说,本文通过概念解释、代码用例分析和最佳实践分享,全面介绍了Java异常处理机制及相关技术特点。对于Java程序员来说,掌握异常和错误的区别,以及熟练运用Java中的异常处理机制,对于编写和维护可靠程序至关重要。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 核心技术面试精讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(208)

  • 最新
  • 精选
  • 继业(Adrian)
    假如你开车上山,车坏了,你拿出工具箱修一修,修好继续上路(Exception被捕获,从异常中恢复,继续程序的运行),车坏了,你不知道怎么修,打电话告诉修车行,告诉你是什么问题,要车行过来修。(在当前的逻辑背景下,你不知道是怎么样的处理逻辑,把异常抛出去到更高的业务层来处理)。你打电话的时候,要尽量具体,不能只说我车动不了了。那修车行很难定位你的问题。(要补货特定的异常,不能捕获类似Exception的通用异常)。还有一种情况是,你开车上山,山塌了,这你还能修吗?(Error:导致你的运行环境进入不正常的状态,很难恢复) ------------------ 思考问题:由于代码堆栈不再是同步调用那种垂直的结构,这里的异常处理和日志需要更加小心,我们看到的往往是特定 executor 的堆栈,而不是业务方法调用关系。对于这种情况,你有什么好的办法吗? ------------------ 业务功能模块分配ID,在记录日志是将前后模块的ID进行调用关系的串联,一并跟任务信息,进行日志保存。

    作者回复: 形象!

    2018-09-21
    9
    411
  • 钱宇祥
    1.异常:这种情况下的异常,可以通过完善任务重试机制,当执行异常时,保存当前任务信息加入重试队列。重试的策略根据业务需要决定,当达到重试上限依然无法成功,记录任务执行失败,同时发出告警。 2.日志:类比消息中间件,处在不同线程之间的同一任务,简单高效一点的做法可能是用traceId/requestId串联。有些日志系统本身支持MDC/NDC功能,可以串联相关联的日志。

    作者回复: 很棒的总结

    2018-05-08
    2
    106
  • 约书亚
    先说问题外的话,Java的checked exception总是被诟病,可我是从C#转到Java开发上来的,中间经历了go,体验过scala。我觉得Java这种机制并没有什么不好,不同的语言体验下来,错误与异常机制真是各有各的好处和槽点,而Java我觉得处在中间,不极端。当然老师提到lambda这确实是个问题... 至于响应式编程,我可以泛化为异步编程的概念嘛?一般各种异步编程框架都会对异常的传递和堆栈信息做处理吧?比如promise/future风格的。本质上大致就是把lambda中的异常捕获并封装,再进一步延续异步上下文,或者转同步处理时拿到原始的错误和堆栈信息

    作者回复: 是的,非常棒的总结,归根结底我们需要一堆人合作构建各种规模的程序,Java异常处理有槽点,但实践证明了其能力; 类似第二点,我个人也觉得可以泛化为异步编程的概念,比如Future Stage之类使用ExecutionException的思路

    2018-05-08
    65
  • 飞云
    能不能讲下怎么捕捉整个项目的全局异常,说实话前两篇额干货都不多,希望点更实在的干货

    作者回复: 谢谢建议,极客课程设计是尽量偏向通用场景,我们掉坑里,往往都不是在高大上的地方;全局异常Spring MVC的方式就很实用;对与干货,你是希望特定场景,特定问题吗?说说你的想法

    2018-05-08
    37
  • 小绵羊拉拉
    看完文章简单认识一些浅层的意思 但是我关注的 比如try catch源码实现 涉及 以及 文章中提到 try catch 产生 堆栈快照 影响jvm性能等 一笔带过 觉得不太过瘾。只是对于阿里的面试 读懂这篇文章还是不够。还希望作者从面试官的角度由浅入深的剖析异常处理 最后还是 谢谢分享

    作者回复: 谢谢反馈,如果不做jvm或非常底层开发,个人没有看到这些细节的实际意义,如果非要问可以鄙视他:-) 创建Throwable因为要调用native方法fillInStacktrace;至于try catch finally,jvms第三章有细节,也可以自己写一段程序,用javap反编译看看 goto、异常表等等

    2018-05-08
    28
  • Caliven
    ClassNotFoundException是在写编码的时候编译器就能告诉你这个地方需要捕获异常,如:你使用Class.forName的时候就必须要你捕获或者throws这个异常。 而NoClassDefFoundError在Javac已经把程序成功的编译成字节码文件了,当JVM进程启动,通过类加载器加载字节码文件,然后由JIT去解释字节码指令的时候,在classpath下找不到对应的类进行加载时就会发生NoClassDefFoundError这个错误。 我也不知道我的理解正确么?

    作者回复: 基本正确,另外jit不是解释而是编译,解释是解释器的工作

    2018-07-25
    2
    23
  • James
    个人觉得checked exception / unchecked exception 分别翻译为 检查型异常/非检查型异常 更加好理解。 可检查异常容易被理解为可以不检查。

    作者回复: 有道理,谢谢指出

    2018-05-08
    3
    19
  • 五年
    老师讲的很好 😄 不过理论讲过之后很容易忘 老师可以开一个github的代码库,将课程的最佳实践还有反例放进去吗

    作者回复: 有打算,最近出差,黑白颠倒,回去找机会弄下

    2018-05-24
    15
  • 美猴王
    提供一种思路:结合项目管理中对风险的分类,与文章的exception和errer做个关系对应。 checked exception(编译期异常)对应已知风险; unchecked exception(运行时异常)对应可预测异常; error(严重错误)对应不可预测风险;

    作者回复: 很新颖的思路

    2019-01-23
    12
  • Attract
    对于日志里面我们看到的往往是特定 executor 的堆栈,而不是业务方法调用关系这种情况,我在公司推行的是自定义异常,自定义的异常有一个错误码,这个错误码需要细到某个业务的某个方法的某种错,这样排查问题会很方便,但是写的时候就比较麻烦,文档也比较多

    作者回复: 嗯,有些类似trace id的思路,构建树形堆栈也有帮助

    2018-05-08
    11
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部