异常处理
异常概述
如果一个方法不能按照正常的执行途径完成任务,就可以通过另一种途径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,方法会立即退出同时不返回任何值。另外,调用这个方法的其他代码也无法正常执行,异常处理机制会将代码执行交给异常处理器。
异常分类(继承体系)
Throwable
Java将所有非正常的情况分为两种:异常(Exception)和错误(Error),他们都继承自Throwable。
Error
Error错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可捕获,将导致应用程序中断。应用程序不会抛出异常对象。如果出现这种错误,除了告知用户,剩下的就是使程序安全终止。
Exception
异常被分为两大类:Checked异常和Runtime异常(运行时异常)。所有的RuntimeException类及其子类都是运行时异常;不是RuntimeException类及其子类的异常实例则被称为Checked异常。
Checked异常
检查异常一般是外部错误,这种异常都是发生在编译阶段的,Java编译器会强制程序处理此类异常。这类异常一般包括如下几方面:
- 试图在文件尾部读取数据;
- 试图打开一个错误格式的URL;
- 试图根据给定的字符串查找class对象,而这个字符串表示的类并不存在。
如IOException
、SQLException
。
对于Checked异常的处理方式有两种: - 当前方法明确知道如何处理的,则使用
try{}catch(){}
块来捕获异常,然后在对应的catch块中修复该异常。 - 当前方法不知道如何处理该异常,则应该在定义方法时抛出该异常。
RuntimeException
RuntimeException
是那些可能在Java虚拟机运行期间抛出异常超类。如果出现了RuntimeException
则一定是编程的错误。
异常处理
使用try{}catch(){}捕获异常
将可能出现异常的代码放在try块中,如果执行try块里的业务逻辑代码出现异常,系统会自动生成一个异常对象,该对象被提交给Java运行时环境。当Java运行时环境收到异常时,会寻找能处理该异常对象的catch块,如果找到合适的catch块,则会把该异常对象交给catch块处理,这个过程叫做捕获异常;如果未找到合适的catch块,则运行时环境终止,Java程序也将退出。
- 使用catch进行捕获时,父类异常应该排在子类异常之后。(先捕获小异常,再捕获打异常)
- 捕获多种类异常时,多种类异常之间用竖线
|
隔开。 - 异常变量有隐式
final
修饰,因此程序不能对异常变量重新赋值。
所有异常对象常用方法:
getMessage()
:返回该异常的详细描述字符串;printStackTrace()
:将该异常的跟踪栈信息输出到标准错误输出;printStackTrace(PrintStream s)
:将该异常栈信息输出到指定输出流;getStackTrace()
:返回该异常的跟踪栈信息。
throws声明抛出异常
使用throws声明抛出异常的思路是:当前方法不知道如何处理这种类型的异常,该异常应该由上级调用者处理;如果是
main()
方法也不知道如何处理这种异常,也可以使用throws
声明抛出异常,该异常将交给JVM处理。JVM对这种异常的处理方法是:打印出异常的跟踪栈信息,并终止程序运行。(这就是应用程序遇到异常后自动结束的原因)
使用: throws仅跟在方法名之后,可以声明多个异常,使用逗号隔开。
限制: 方法重写中,子类声明抛出异常范围必须小于等于父类声明抛出异常的范围。
使用throw抛出异常
throw
可以在程序中单独使用,自行抛出异常,throw
后跟异常对象而不是异常类,并且每次只允许抛出一个异常实例。
当Java运行时接收到开发者自行定义的异常时,同样会终止当前的执行流,跳到该异常对应的catch
块,由catch
块来处理该异常。
自定义异常
一般情况下,程序很少抛出系统自定义异常,因为异常类通常包含异常名称和异常信息,所以在抛出异常时需要选择合适的异常类,便于问题的排查和定位。这种情况下常常需要自定义异常类。
自定义异常都需要继承Exception
类,如果希望自定义Runtime
异常,则需要继承RuntimeException
类。定义异常类通常需要提供两个构造器:
- 无参构造器;
- 带一个字符串的参数构造器,这个字符串将作为该异常对象的描述信息。
以下程序实现了一个自定义异常:
/**
* @author windmyf
*/
public class TestException extends Exception {
/**
* 无参构造器
*/
public TestException(){}
/**
* 带参构造
* @param message 异常信息
*/
public TestException(String message){
super(message);
}
}