专栏首页ObjectiveSQLJava 中的Exception 有什么用?

Java 中的Exception 有什么用?

Exception 的作用,这个问题是一个开放性的问题,没有标准的答案,不同经历的人可能会有不同的答案,也就是说经历过惨痛的经历后,才会对Java Exception 有深刻的认识,单纯理论学习,按部就班的按所谓的规范使用,无法准确的表达出Java Exception 的内在逻辑。

Exception 含义

Exception,顾名思义,代表着程序运行的过程中出现一种不正常的状态,需要中止程序的持续运行,同时又能快速的发现程序为什么会出现错,通过异常的信息能够快速定位,所以异常需要提供错误的上下文的状态信息,尤其是应用系统自身抛出的异常,需要将上下文状态尽可能多的输出,有助于排查和定位。Java 中的NullPointerException 对外提供的信息极少,所以应用系统应该尽可能catch 这类异常,包装为信息量更加丰富的异常抛出。

Exception 也是一种程序逻辑控制的方式,是程序健壮性的一种表现。其实,大都数异常,程序都应该有一定的相应的处理逻辑,例如,ArrayIndexOutOfBoundsException,这类异常在编码过程中应该能够被预见,并需要做出现相应的逻辑控制,有经验的程序员,在编码的过程中就已经考虑到各种异常的情况,待整个系统上线后,出现的问题相对较少,而普通的程序员往往只保证程序在Happy Case 时能够正常运行,却忽略了各种异常情况,往往是在出现问题后进行补救,导致程序在反复补救后,逻辑混乱,这也就是很多项目早期的代码质量高,经过一段时间后,代码惨不忍睹的根源。

Exception 的处理方式

什么时候需要catch Exception?什么时候需要throw 呢?这也是不会有标准答案的过程,Java 本身也没有给出标准答案,也没有指导原则。但经过无数次实践的经验后,你就能体会对异常的不同处理方式,对系统逻辑的稳定性性有着截然不同的影响,往往出现很诡异的Bug时,同时可参考的日志或其它关键丢失,导致故障不能及时解决,才会发现关键的位置异常被人为的隐藏是多么愚蠢的行为。

我在使用一个开源的框架时,时常会发现重要的异常信息被隐藏,导致花费大量的时间去跟踪代码。异常在什么时候需要throw,什么时候需要catch,原则其实很简单:

  1. 异常在能够完全掌控的情况下,而且也有明确的逻辑处理时,需要catch,并进行相应的处理。同时,也需要关注外部程序是否需要感知异常,如果需要,则封装新的异常后重新throw;
  2. 无法决定处理逻辑的情况下,需要将所有异常throw,让外部程序决定处理逻辑。同时,针对内部的信息含量较少的Runtime 型的异常,需要额外封装,避免在同一行代码中,无法确定哪一个对象为null。

Exception 定义

什么时候定义Exception 同样是没有任何指导原则,不同的技术框架中对异常定义的方式和方法都不太一样,毕竟每个应用系统的逻辑结构和复杂度都不太一定,我根据自身的经验整理了两个指导原则:

  1. 程序需要中止,自身又无法完整的处理逻辑转折,只能由外部调用者根据异常的信息,作为合理的逻辑处理,例如:数据采集时,出现了非法的数据或字符串,采集程序是无法判断逻辑转折后,就如何处理,同时又需要明确区分非常数据,甚至需要定义出错误的类型,由外部程序决定是忽略还是终止执行,在这种情况下需要定义明确的异常,用于标识错误的类型。
  2. 内部程序处理过程中出现太多异常,并且这类异常具有共同的特性(例如:ClassNotFountException, NoSuchMehtodException 等),不需要外部程序对这类异常分别处理时,需要定义一个异常用于包装内部异常,提升代码的可读性。
  3. 错误信息的补充,例如上文所提到的NullPointerException,应用系统程序需要为此异常补充更完整的信息,便于外部程序或日志系统提供足够的信息,便于故障的解决;

Exception 和 RuntimeException 有什么区别,在什么场景下定义,也是一个仁者见仁,智者见智的问题,Java 没有任何指导建议,按我个人的判断,JDK中也有很多的定义也不是特别合理,例如:IndexOutOfBoundsException 应该是一个Exception, JDK 却定义为RuntimeExcption 这类错误需要明确的提醒外部程序对数组进行逻辑限制,很多应用系统在总是在出现错误后,才能主动Cache 这类异常;然而像 ClassNotFoundException 这类异常在极少数状态下才会进行逻辑处理JDK 却定义为Exception 导致很多反射类的项目的处理逻辑变得复杂,NullPointerException 也是经常出现的,但定义为RuntimeException 是合理的,可能因为JDK 程序从逻辑上根本无法捕捉NullPointerException,应该是在JVM 执行过程中才能够进行逻辑判断,具体并未研究。

经过上面的两个示例也很容易看出Exception 和RuntimeException 有什么区别,JDK 的设计应该从外部程序使用的角度进行异常设计,由于外部程序导致的异常,并且外部程序应当有逻辑处理异常状态,这类异常理应定义为Exception,而其它由于JVM 在编码期无法判断,也无法从语法层面提供解释的Exception 应该定义为RuntimeException。

结论

针对Java 异常的解读是我个人的见解,就像古诗词一样,不同人有不同的解读,相信JDK 的设计者也无法给 Java Exception 一个明确的解释和原则,只能靠历史经验的积累和不断的错误中,逐形成相对完整的理论,供后人学习。

原文链接:http://www.objsql.com/2020/10/12/interview/

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 关系数据库设计之(双外键 )

    本文的设计方法主要应用于大型综合数据分析系统,由于其接入数据源种类较多且数据不稳定。所谓不稳定是指数据进入数据仓库后,外部数会发生变化,关键是这些变化会影响整体...

    ObjectiveSQL
  • 推荐一款技术人必备的接口测试神器:Apifox

    作为互联网行业技术从业者,接口调试是必不可少的一项技能,通常我们都会选择使用 Postman 这类工具来进行接口调试,在接口调试方面 Postman 做的确实非...

    测试开发技术
  • Postman Postman测试接口之POST提交本地文件数据

    接口地址:http://183.xxx.xxx.xxx:23333/ditui/fileupload

    授客
  • Java每日一练(2017/7/15)

    最新通知 ●回复"每日一练"获取以前的题目! ●【新】Ajax知识点视频更新了!(回复【学习视频】获取下载链接) ●答案公布时间:为每期发布题目的第二天 ★【新...

    Java学习
  • PHP 面向对象 接口

    使用接口 interface,可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。 要实现一个接口,使用 implements 操作符。 接口中定义...

    康怀帅
  • WPF 客户端开发需要知道的触摸失效问题

    在说 WPF 开发的时候,如果开发的应用是触摸应用,那么熟悉的小伙伴会说到触摸失效问题。从分类上触摸失效有系统的触摸失效,应用程序的触摸失效,同时触摸失效指的不...

    林德熙
  • App开发:模拟服务器数据接口 - MockApi

    为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块。本篇文章就尝试为使用gra...

    用户1172465
  • OpenSCAD 建模:矿泉水瓶盖

    张高兴
  • OpenSCAD 建模:矿泉水瓶花洒

    张高兴
  • 接口测试基础知识

    外部接口:例如公司的项目涉及到支付这块,微信支付,支付宝支付,银联支付,不会是自己公司开发的接口,因为用户的数据在阿里云和腾讯那边,想动支付宝或者是微信中用户钱...

    清菡

扫码关注云+社区

领取腾讯云代金券