使用try-catch-finally处理异常

用法一览

try{
    //需要被检测的异常代码
} catch(Exception e){
    //异常处理,即处理异常代码
}
finally{
    //一定会被执行的代码
}

可以在catch部分加上一句打印异常

System.out.println(e.ToString());

try+catch+finally

Java通过面向对象的方法来处理异常。 在一个方法的运行过程中,如果发生了异常,则这个方法生成代表该异常的一个对象,并把它交给运行时系统,运行时系统寻找相应代码来处理这一异常。

我们把生产例外对象并把它提交给运行时系统的过程称为throw一个异常。

运行时系统在方法的调用栈中查找,从生成例外的方法开始回溯,知道找到相应的异常处理的方法为止,这一过程称为捕获(catch)一个例外。

Throwable类及其子类

java用面向对象的方法处理异常,必须建立类的层次。类Throwable位于这一类层次的最顶层,只有它的后代才可以作为一个异常被抛弃。
使用try-catch-finally处理异常_第1张图片

Throwable有两个直接子类:ErrorException

  • Error类对象(如动态连接错误),有Java虚拟机生成并抛出(通常,Java程序不对这类例外进行处理);

  • Exception类对象是Java程序处理或抛出的对象。它有各种不同的分类分别对应不同类型的异常。其中类RuntimeException代表运行时由Java虚拟机生成的例外,如算术运算异常ArithmeticException由除0错等导致)、数组越界异常ArrayIndexOutOfBoundsException等;其他则为非运行时异常,如输入输出异常IOException。Java编译器要求Java程序必须捕获或声明所有的非运行时例外,但对运行时例外可以不做处理。也就是说,RuntimeException要自己写catch块处理掉。

异常处理关键字

try
catch
catch语句的参数包括一个异常类型和异常对象,异常类型必须为Throwabled的子类。

catch语句可以有多个,分别处理不同类的异常。运行时,系统从上到下分别对每个catch语句处理的异常类型进行检测,直到找到类型相匹配的catch语句。

这里的类型匹配指的是catch所处理的异常类型与生成的异常对象完全一致或者是它的父类,所以catch语句的排序顺序应该是从特殊到一般。

finally
无论try程序块抛不抛出异常,无论catch有没有捕获到异常,finally程序块都要被执行。 它提供了统一的出口,通常可以进行资源的清除工作,如关闭打开的文件等。

throws

throws总是出现在一个函数头中,用来标明该成员函数可能抛出的各种异常。对大多数Exception子类来说,Java编译器会强迫你声明在一个成员函数中抛出的异常的类型。

如果异常的类型是ErrorRuntimeException,或它们的子类,这个规则不起作用,因为这在程序的正常部分中是不期待出现的。 如果你想明确地抛出一个RuntimeException,你必须用throws语句来声明它的类型。

throw
throw总是出现在函数体中,用来抛出一个异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。

语句流程

try的嵌套

可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部,写另一个try语句保护其他代码。每当遇到一个try语句,异常的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种异常进行处理,堆栈就会展开,直到遇到有处理这种异常的try语句。

try+catch程序块的执行流程与结果

首先执行的是try语句块中的语句,这时可能会有以下三种情况:
1.如果try块中所有语句正常执行完毕,那么就不会有其他的“动做”被执行,整个try-catch程序块正常完成。

2.如果try语句块在执行过程中碰到异常V,这时又分为两种情况进行处理:
–>如果异常V能够被与try相应的catch块catch到,那么第一个catch到这个异常的catch块(也是离try最近的一个与异常V匹配的catch块)将被执行;如果catch块执行正常,那么try-catch程序块的结果就是“正常完成”;如果该catch块由于原因R突然中止,那么try-catch程序块的结果就是“由于原因R突然中止(completes abruptly)”。
–>如果异常V没有catch块与之匹配,那么这个try-catch程序块的结果就是“由于抛出异常V而突然中止(completes abruptly)”。

3. 如果try由于其他原因R突然中止(completes abruptly),那么这个try-catch程序块的结果就是“由于原因R突然中止(completes abruptly)”。

try+catch+finally程序块的执行流程与结果

1.如果try块中所有语句正常执行完毕,那么finally块的居于就会被执行,这时分为以下两种情况:
–>如果finally块执行顺利,那么整个try-catch-finally程序块正常完成。
–>如果finally块由于原因R突然中止,那么try-catch-finally程序块的结局是“由于原因R突然中止(completes abruptly)”

2.如果try语句块在执行过程中碰到异常V,这时又分为两种情况进行处理:
–>如果异常V能够被与try相应的catch块catch到,那么第一个catch到这个异常的catch块(也是离try最近的一个与异常V匹配的catch块)将被执行;这时就会有两种执行结果:

–>如果catch块执行正常,那么finally块将会被执行,这时分为两种情况:

–>如果finally块执行顺利,那么整个try-catch-finally程序块正常完成。
–>如果finally块由于原因R突然中止,那么try-catch-finally程序块的结局是“由于原因R突然中止(completes abruptly)”

–>如果catch块由于原因R突然中止,那么finally模块将被执行,分为两种情况:

–>如果如果finally块执行顺利,那么整个try-catch-finally程序块的结局是“由于原因R突然中止(completes abruptly)”。
–>如果finally块由于原因S突然中止,那么整个try-catch-finally程序块的结局是“由于原因S突然中止(completes abruptly)”,原因R将被抛弃。 如果在你的代码中期望通过捕捉被调用的下级函数的异常来给定返回值,那么一定要注意你所调用的下级函数中的finally语句,它有可能会使你throw出来的异常并不能真正被上级调用函数可见的。

–>如果异常V没有catch块与之匹配,那么finally模块将被执行,分为两种情况:

–>如果finally块执行顺利,那么整个try-catch-finally程序块的结局就是“由于抛出异常V而突然中止(completes abruptly)”。
–>如果finally块由于原因S突然中止,那么整个try-catch-finally程序块的结局是“由于原因S突然中止(completes abruptly)”,异常V将被抛弃

3.如果try由于其他原因R突然中止(completes abruptly),那么finally块被执行,分为两种情况:

–>如果finally块执行顺利,那么整个try-catch-finally程序块的结局是“由于原因R突然中止(completes abruptly)”。
–>如果finally块由于原因S突然中止,那么整个try-catch-finally程序块的结局是“由于原因S突然中止(completes abruptly)”,原因R将被抛弃。

try+catch+finally程序块中的return

写在trycatch中的return语句不会真的从函数中跳出,而是执行finally块。上级调用函数能够获取到的只是finally中的返回值,trycatch中的return语句只是转移控制权的作用。

如何抛出异常

如果你知道你写的某个函数有可能抛出异常,而你又不想在这个函数中对异常进行处理,只是想把它抛出去让调用这个函数的上级调用函数进行处理,那么有两种方式可供选择:

第一种方式:直接在函数头中throws SomeException,函数体中不需要try/catch。
第二种方式:使用try/catch,在catch中进行一定的处理之后(如果有必要的话)抛出某种异常。

adrupt completion

complete adruptly 主要包含两种大的情形:
abrupt completion of expressions and statements,下面就分两种情况进行解释。

Normal and Abrupt Completion of Evaluation

每一个表达式(expression)都有一种使得其包含的计算得以一步步进行的正常模式,如果每一步计算都被执行且没有异常抛出,那么就称这个表达式“正常结束(complete normally)”;如果这个表达式的计算抛出了异常,就称为“异常结束(complete abruptly)”。异常结束通常有一个相关联的原因(associated reason),通常也就是抛出一个异常V。

Normal and Abrupt Completion of Statements

正常情况我们就不多说了,在这里主要是列出了abrupt completion的几种情况:

–>break, continue, and return 语句将导致控制权的转换,从而使得statements不能正常地、完整地执行。
–>某些表达式的计算也可能从java虚拟机抛出异常,这些表达式在上一小节中已经总结过了;一个显式的的throw语句也将导致异常的抛出。抛出异常也是导致控制权的转换的原因(或者说是阻止statement正常结束的原因)。 如果上述事件发生了,那么这些statement就有可能使得其正常情况下应该都执行的语句不能完全被执行到,那么这些statement也就是被称为是complete abruptly.

一些tips:

  1. try、catch、finally语句中,在如果try语句有return语句,则返回的之后当前try中变量此时对应的值,此后对变量做任何的修改,都不影响try中return的返回值

  2. 如果finally块中有return 语句,则返回try或catch中的返回语句忽略。

  3. 如果finally块中抛出异常,则整个try、catch、finally块中抛出异常。

所以使用try、catch、finally语句块中需要注意的是

  1. 尽量在try或者catch中使用return语句。通过finally块中达到对try或者catch返回值修改是不可行的。

  2. finally块中避免使用return语句,因为finally块中如果使用return语句,会显示的消化掉try、catch块中的异常信息,屏蔽了错误的发生

  3. finally块中避免再次抛出异常,否则整个包含try语句块的方法回抛出异常,并且会消化掉try、catch块中的异常

引用整理自:
https://cloud.tencent.com/developer/article/1088141
https://blog.csdn.net/qq_22860341/article/details/73610537
https://blog.csdn.net/qq_33535433/article/details/79293809

你可能感兴趣的:(Java)