异常类型
异常的根类是 java.lang.Throwable
所有异常类都直接或间接继承自Throwable
。可以通过继承 Exception
或 Exception
的子类来自定义异常类。
异常可以分为三种类型:
- 系统错误:由Java虚拟机抛出,用
Error
类表示。这类异常发生后,只能终止程序。 - 异常:由程序和外部环境引起,用
Exception
类表示。这类异常能够被程序捕获处理。 - 运行时异常:程序设计错误引起,用
RuntimeException
表示。运行时异常通常表明程序编译错误。
Runtime Exception
、Error
以及它们的子类都称为 免检异常
所有的其他异常都称为 必检异常 意味着编译器会强制用try—catch
块处理它们,或 在方法头进行声明
异常声明
免检异常不需要在方法头显示声明。必检异常必须在方法头用throws
关键字声明。
注意:如果父类的方法中没有声明异常,在子类中重写父类方法时就不能声明异常。
异常处理
如果try块中某条语句抛出异常,Java就会跳过try块中其他语句,然后开始查找处理异常的程序。可以从当前方法开始,沿着方法调用链,按照异常的反向传播方法找到这个处理器。也就是说,从第一个catch块到最后一个catch块逐个检查,判断catch块中的异常类型是否与该异常对象的类型相同。相同就执行该代码,不是就退出该方法,把异常传给方法的调用者。直到异常被捕获或传给main方法,如果在主函数中也找不到处理器,程序就会终止并在控制台上打印出错信息。
注意:
1.各种异常类可以从一个共同的父类派生。如果catch块可以捕获一个父类异常,那么它就能捕获到父类异常的所有子类异常对象。
2.在catch块中异常的处理顺序是十分重要的。如果父类的catch块出现在子类异常前面,就会导致编译错误。
3.如果方法声明了一个必检异常,就必须在try-catch中调用或者在调用方法中声明会抛出的异常。
对于使用同样的代码处理多种异常的情况,可以使用multi-catch feature简化异常代码的编写。
catch(Exception1 | Exception2 | ...|Exceptionk ex){ }
每个异常类型用竖线( | )分隔。如果其中一个异常被捕获,则执行处理的代码。
finally语句块
首先,要执行finally语句块,必须是try块执行的前提下,如果try块没有执行,finally语句不会被执行。
有几种情况:
- try块中没有出现异常,执行finally语句,然后执行try语句的下一条语句。
- 如果try块语句出现异常并被捕获,会跳过try块其他语句,执行catch和finally语句。然后执行try块的下一条语句。
- 如果try块中的异常没有被捕获,finally依然会执行,然后将异常返回给方法的调用者。
4.如果try块中有return语句,finally语句还是会执行。
在执行finally语句前会将try语句的变量缓存,然后执行finally语句,在返回缓存的变量。要看缓存的是变量还是对象,如果是对象,finally语句也有return语句,那么返回的对象会改变。