异常处理try,catch,finally
在JAVA语言出现以前,传统的异常处理方式多采用返回值来表示程序出现的异常情况,这种方式虽然为程序员所熟悉,但却有多个坏处。
首先,一个API可以返回任意的返回值,而这些返回值本身并不能解释该返回值是否代表一个异常情况发生了和该异常的具体情况,需要调用API的程序自己判断并解释返回值的含义。
其次,并没有一种机制来保证异常处理情况一定会得到处理,调用程序可以简单的忽略该返回值,需要调用API的程序员记住去检测返回值并处理异常情况。这种方式还让程序代码变得冗长,尤其是当进行IO操作等容易出现异常情况的处理时,代码的很大部分用于处理异常情况switch分支,程序代码的可读性变得很差。
异常处理机制
当程序中抛出一个异常后,程序从程序中导致异常的代码中跳出,java虚拟机检测寻找和try关键字匹配的处理该异常的catch块,如果找到,将控制权交到catch块中的代码,然后继续往下执行程序,try块中发生异常的代码不会被重新执行。如果没有找到处理还一场的catch块,在所有的finally块代码被执行和当前线程所属的ThreadGroup的uncaughtException方法被调用后,遇到异常的当前线程被终止。
异常的捕获和处理
Throwable,Error和Exception
Java异常结构中定义有Throwable类,Exception和Error是其派生的两个字类。其中Exception表示由于网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常;而Error表示Java运行时环境出现的错误,例如:JVM内存资源耗尽等。
try——catch语句(重点)
try{}语句指定了一段代码,该段代码就是一次捕获并处理例外的范围。在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句分别对这些异常作相应的处理;
如果没有发生异常,所有的catch代码块都被忽略不执行;
在catch语句块中是对异常进行处理的代码;
在catch中声明的异常对象(catch(SomeException e))封装了异常事件发生的信息,在catch语句块中可以使用使用这个对象的一些方法获取这些信息。
每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不用类型的异常‘4
catch捕获的异常类型由上至下的捕获顺序应是子类到父类的。
try{
...
}catch(NullPointerException e){
...
}catch(RuntimeException e){
...
}catch(Exception e){
...
}
finally作用
finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序其他部分以前。能够对程序的状态做统一管理;
无论try所指定的程序块中是否抛出异常,finally所制定的代码都要被执行;
通常在finally语句中可以进行资源的释放工作,如关闭打开的文件,删除临时文件等
throw关键字
当程序发生错误而无法处理的时候,会抛出对应的异常对象,除此之外,在某些时刻,程序员可能会想要自行抛出异常,例如在异常处理结束后,再将异常抛出,让下一层异常处理块来捕捉,若想要自行抛出异常,可以使用“throw”关键字,并生成指定的异常对象后抛出。
- 例如:throw new ArithmeticException();
throws关键字
程序中会声明许多方法(Method),这些方法中可能会因某些错误而引发异常,但是程序员不希望直接在这个方法中处理这些异常,而希望调用这个方法的方法来统一处理,这时候可以使用“throws”关键词来声明这个方法将会抛出异常。
重写方法时的throws
- 如果使用继承时,在父类的某个方法上声明了throws某些异常,而在子类中重新定义该方法时,可以:
— 不处理异常(重新定义时不设定throws)
— 仅可throws父类中声明的部分异常
— 可throws父类方法中抛出异常的子类异常
- 但是不可以:
— throws出额外的异常
— throws父类方法中抛出异常的父类异常
例子:
try {
tryCode - 尝试执行代码块
}
catch(err) {
catchCode - 捕获错误的代码块
}
finally {
finallyCode - 无论 try / catch 结果如何都会执行的代码块
}
RuntimeException
RuntimeException类属于非检查异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现。因此它们不受编译器检查与处理或声明规则的限制。
常见RuntimeException:
- IllegalArgumentException 表明向方法传递了一个不合法或不正确的参数
- NullPointerException 当应用程序试图在需要对象的地方使用null时,抛出该异常
- ArrayIndexOutOfException 当使用的数组下标超出数组允许范围时,抛出该异常
- ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常
- NumberFormatException 当试图将字符串转换成一种数值类型,但字符不符合适当格式时,抛出该异常
printStackTrace
- Throwable中定义了一个方法可以输出错误信息,用来跟踪异常事件发生时执行堆栈的内容。
— void printStackTrace()
getMessage
- Throwable中定义了一个方法可以得到有关异常事件的信息。
— String getMessage()
getCause
- 很多时候,当一个异常由另一个异常导致而被抛出的时候,Java库和开放源代码会将一种异常包装成另一种异常。这时,日志记录和打印根异常就变的非常重要。Java异常类提供了getCause()方法来检索导致异常的原因,这些可以对异常根层次的原因提供更多的信息。
- 该Java实践对代码的调试或故障排除有很大的帮助。另外,如果要把一个异常包装成另一种异常,构造一个新异常就要传递原异常。
— Thrwoable getCause() 获取该异常出现的原因