Java 进阶之路:异常处理的内在原理及优雅的处理方式

永远不要期待程序在完全理想的状态下运行,异常往往不期而遇,如果没有完善的异常处理机制,后果可能是灾难性的。对于 Java 工程师而言,合理地处理异常是一种基本而重要的能力,然而,在近来的面试中,笔者发现很多应聘者对异常处理的内在原理几无了解,现场手写的异常处理代码也极为“原始”。

鉴于此,笔者将通过本场 Chat 为读者呈现 Java 异常处理的内在原理、处理原则及优雅的处理方式。主要内容如下:

  1. Java 异常的层次结构和处理机制
  2. Java 异常表与异常处理的内在原理
  3. .Java 异常处理的基本原则
  4. 优雅地处理 Java 异常案例
  5. Java 异常简介

对于 Java 工程师而言,异常应该并不陌生,作为本场 Chat 的引入部分,对 Java 异常的基础知识仅作简要回顾,本文主体将聚焦于深入解读 Java 异常的底层原理和异常处理实践。

1.1 Java 异常类层次结构

在 Java 中,所有的异常都是由 Throwable 继承而来,换言之,Throwable 是所有异常类共同的“祖先”,层次结构图如下所示(注:Error、Exception 的子类及其孙子类只列出了部分):

1.2 Java 异常类相关的基本概念

Throwable

作为所有异常类共同的“祖先”,Throwable 在“下一代”即分化为两个分支:Exception(异常)和 Error(错误),二者是 Java 异常处理的重要子类。

Error

Error 类层次结构用于描述 Java 运行时系统的内部错误和资源耗尽错误,这类错误是程序无法处理的严重问题,一旦出现,除了通告给用户并尽可能安全终止程序外,别无他法。

常见的错误如:

JVM 内存资源耗尽时出现的 OutOfMemoryError
栈溢出时出现的 StackOverFlowError
类定义错误 NoClassDefFoundError
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,它们在应用程序的控制和处理能力之外,一旦发生,Java 虚拟机一般会选择线程终止。对于新手小白想更轻松的学好Java提升,Java架构,web开发、大数据,数据分析,人工智能等技术,这里给大家分享系统教学资源,扩列下我尉(同英):CGMX9880 【教程/工具/方法/解疑】

Exception

相较于 Error,Exception 类层次结构所描述的异常更需要 Java 程序设计者关注,因为它是程序本身可以处理的。Exception 类的“下一代”分化为两个分支:RuntimeException + 其它异常。

划分两个分支的原则为:

由程序错误导致的异常属于 RuntimeException;
而程序本身没有问题,但由于 I/O 错误之类问题导致的异常属于其它异常。
关于异常和错误的区别:通俗地讲,异常是程序本身可以处理的,而错误则是无法处理的。

可检查异常

可检查异常也称为已检查异常(Checked Exception),这类异常是编译器要求必须处置的异常。在工程实践中,程序难免出现异常,其中一些异常是可以预计和容忍的,比如:

读取文件的时候可能出现文件不存在的情况(FileNotFoundException),但是,并不希望因此就导致程序结束,那怎么办呢?
通常采用捕获异常(try-catch)或者抛出异常(throws 抛出,由调用方处理)的方式来处理。

可检查异常虽然也是异常,但它具备一些重要特征:可预计、可容忍、可检查、可处理。因此,一旦发生这类异常,就必须采取某种方式进行处理。

Java 语言规范将派生于 Error 类或 RuntimeException 类之外的所有异常都归类为可检查异常,Java 编译器会检查它,如果不做处理,无法通过编译。

不可检查异常

与可检查异常相反,不可检查异常(Unchecked Exception)是 Java 编译器不强制要求处置的异常。Java 语言规范将 Error 类和 RuntimeException 及其子类归类为不可检查异常。

为什么编译器不强制要求处置呢?不是因为这类异常简单,危害性小,而是因为这类异常是应该尽力避免出现的,而不是出现后再去补救。以 RuntimeException 类及其子类为例:

NullPointerException(空指针异常)
IndexOutOfBoundsException(下标越界异常)
IllegalArgumentException(非法参数异常)
这些异常通常是由不合理的程序设计和不规范的编码引起的,工程师在设计、编写程序时应尽可能避免这类异常的发生,这是可以做到的。在 IT 圈内有个不成文的原则:如果出现 RuntimeException 及其子类异常,那么可认为是程序员的错误。对于新手小白想更轻松的学好Java提升,Java架构,web开发、大数据,数据分析,人工智能等技术,这里给大家分享系统教学资源,扩列下我尉(同英):CGMX9880 【教程/工具/方法/解疑】

1.3 异常处理机制

在 Java 应用程序中,异常处理机制有:抛出异常、捕捉异常。

抛出异常

这里的“抛出异常”是指主动抛出异常。在设计、编写程序时,我们可以预料到一些可能出现的异常,如 FileNotFoundException,有时候我们并不希望在当前方法中对其进行捕获处理,怎么办呢?抛出去,让调用方去处理,通过 throw 关键字即可完成,如:

throw new FileNotFoundException()

关于抛出异常,还有一个点需要补充,那就是声明可检查异常。在设计程序的时候,如果一个方法明确可能发生某些可检查异常,那么,可以在方法的定义中带上这些异常,如此,这个方法的调用方就必须对这些可检查异常进行处理。

声明异常

根据 Java 规范,如果一个 Java 方法要抛出异常,那么需要在这个方法后面用 throws 关键字明确定义可以抛出的异常类型。倘若没有定义,就默认该方法不抛出任何异常。这样的规范决定了 Java 语法必须强行对异常进行 try-catch。如下的方法签名:

public void foo() throws FileNotFoundException { … }

暗含了两方面的意思:

第一,该方法要抛出 FileNotFoundException 类型的异常;
第二,除了 FileNotFoundException 外不能(根据规范)抛出其它的异常。
那么,如何保证没有除 FileNotFoundException 之外的任何异常被抛出呢?很显然,方式有:

通过合理的设计和编码避免出现其它异常;
如果其它异常不可完全避免(如方法内调用的其它方法明确可能出现异常),就需要 try-cat

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值