深入理解Java中的异常

版权声明:如果觉得文章对你有用,转载不需要联系作者,但请注明出处 https://blog.csdn.net/jinxin70/article/details/82683184

推荐参考:

1. JavaDoc 中搜索Throwable

2. Java异常封装(自己定义错误码和描述,附源码)

3. stackoverflow上的解释

4. Kotlin 和 Checked Exception

引言:

在看Spring mvc源码,看到initWebApplicationContext方法,接着就看到边界检查,方法体抛出异常IllegalStateException。

然后试着回顾一下Java的异常,发现并不能很好的解释给自己听,然后就去搜了一下API和网上的博客。

发现一篇优秀的博文介绍[见推荐参考2]。

首先,API中对Throwable的解释中有:Throwable及其子类(不包括RuntimeException和Error)属于checked exception。

上面一句话这样说更好理解:除了RuntimeException和Error,其他异常都是checked exception,翻译过来叫,"已检查异常",或称"检查性异常"。

那么,什么是checked exception?

checked exception,不是程序可以预见的,不是程序内部控制的,是外部的条件不满足导致的异常,比如无效的用户输入、文件不存在、网络连接错误、数据库连接错误。

必须在代码中显式地处理。比如try-catch块处理,或者给所在的方法加上throws说明,将异常抛到调用栈的上一层。

什么是unchecked exception?

从类层次来讲,RuntimeException的子类都是unchecked exception,语义上的意思,是程序的逻辑错误,需要检查的异常。

比如IllegalArgumentException, NullPointerException和IllegalStateException。

不需要在代码中显式地捕获unchecked异常做处理。

不管是checked exception还是uncheck exception,都是为了语义上的提醒。


进一步认知Java中的异常

checked exception的声明是为了提醒方法调用者(API使用者),这个方法在使用的时候可能因为不满足外部条件而抛出异常。

unchecked exception的声明是为了提醒调用者,程序内部逻辑有错误。

如何使用异常

一般自己写代码,如果是调用第三方方法,需要处理异常,根据自己业务逻辑。如果是service层,就包装成自定义异常,然后抛到上层,如果是UI(Controller)层,就try-catch,返回友好的提示给前台页面。

思考:

假设Java没有checked exception,只有当异常真正出现了,才知道是什么异常(比如参数不匹配、文件不存在、网络连不上等等)。然后回头来对这些异常使用try-catch处理。最遭的是,你调用第三方代码抛出了异常,可是并不知道要捕获什么异常,为此,需要在所有可疑的方法里处理异常。


以下描述来自这里

只要你严格检查被调用函数的异常,尽量不让它们传播,严格限制自己抛出的异常数目,缩小可能出现的异常范围,这种情况是可以避免的。CE 和 union type 强迫你仔细的思考,理顺这些东西之后,你就会发现代码变得非常缜密而优雅。

 Java 要求你必须在函数的类型里面声明它可能抛出的异常(Java 要求你对异常进行 throws 显式声明)。比如,你的函数如果是这样:

void foo(string filename) throws FileNotFoundException
{
  if (...)
  {
    throw new FileNotFoundException();
  }
  ...
}

Java 要求你必须在函数头部写上“throws FileNotFoundException”,否则它就不能编译。这个声明表示函数在某些情况下,会抛出 FileNotFoundException 这个异常。由于编译器看到了这个声明,它会严格检查你对 foo 函数的用法。在调用 foo 的时候,你必须使用 try-catch 处理这个异常,或者在调用的函数头部也声明 “throws FileNotFoundException”,把这个异常传递给上一层调用者。

try
{
    foo("blah");
} 
catch (FileNotFoundException e)
{
    ...
}

这种对异常的声明和检查,叫做“checked exception”。很多语言(包括 C++,C#,JavaScript,Python……)都有异常机制,但它们不要求你在函数的类型里面声明可能出现的异常类型,也不使用静态类型系统对异常的处理进行检查和验证。我们说这些语言里面有“exception”,却没有“checked exception”。


Effective Java中的描述

Use checked exceptions for recoverable conditions and runtime exceptions for programming errors (Item 58 in 2nd edition)

 翻译:对可恢复条件使用已检查的异常,对编程错误使用运行时异常

比如:FileNotFoundException,文件没找到,一般不属于编程错误,是可以恢复的,所以是checked exception。

但是有的异常,比如NumberFormatException,你认为是什么异常呢?

NumberFormatException继承自IllegalArgumentException,而IllegalArgumentException继承自RuntimeException,所以从这个语言层次来说,是属于unchecked exception。

NumberFormatException是数字格式转换错误,可以虽然是内部转化出了错,即内部逻辑错误。但是能不能算是外部传入的参数本身有问题,导致了数字格式转化错误呢?

猜你喜欢

转载自blog.csdn.net/jinxin70/article/details/82683184