一.异常的类型
Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.throwable,Throwable下面有派生了两个子类:Error和Exception。Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份,例如:内存溢出、线程死锁;Exception表示程序还能够克服和恢复的问题,其中又分为运行异常和一般异常。系统异常是软件本身缺陷所导致的,也就是开发人员考虑不周所导致的问题,例如:数组脚本越界(ArrayIndexOutOfBoundsException)、空指针异常(NullPointException)、类转换异常(ClassCastException);普通异常时运行环境的变化或异常所导致的问题,例如:网络断线、硬盘空间不足,发生这样的异常时,程序不应该死掉。
总结:
- Throwable
- Error 程序无法克服和恢复
- Exception 程序可以克服和恢复
- 运行异常 用户无法克服和恢复
- 一般异常 用户可以克服和恢复
二.异常处理
Java为运行异常和一般异常提供了不同的解决方案,编译器强制要求一般必须用try…catch处理或者用throw声明抛出给上层调用的方法处理,所以普通异常又称为checked异常。而运行异常可以处理可以不处理,所以编译器不强制用try…catch处理或throw声明抛出,所以运行异常也称为unchecked异常。
为什么运行异常不用捕获?
编译器之所以不强制要求处理运行时异常,是为了方便开发人员调试,抛出异常后开发人员就知道程序运行过程中出现了什么错误。
常见的运行异常:
- 数组脚本越界(ArrayIndexOutOfBoundsException)
- 空指针异常(NullPointException
- 类转换异常(ClassCastException)
常见的一般异常:
- IO异常(IOException)
- 未找到异常(NotFoundException)
三.发生异常后语句的执行情况
当try里面语句发生异常时:
如果throw异常的话,会执行finally中的代码,其他代码不执行 ;
如果不throw的话,这个catch异常处理相当于程序的一个goto跳转,之后的代码继续执行。并且先执行finally中的语句,然后执行finally下面的语句。
public class Test{
public static void main(String[] args) {
testCatch();
}
public static void testCatch(){
int b = 20;
try{
System.out.println("try block");
int a = 1/0;
b += 80;
}catch (Exception e) {
System.out.println("catch block");
}finally {
System.out.println("finally block");
if (b > 25) {
System.out.println("b>25, b = " + b);
}
}
System.out.println("b = " + b);
}
}
运行结果:
try block
catch block
finally block
b = 20
所以,当我们在方法上用途throws申明抛出异常时,如果有必须要执行的代码,例如:关闭数据库的连接、关闭流时,一定要加finally代码块。
四.finally语句是在return之后还是之前执行?
1.执行try{}里面的return语句
finally{}在return之前执行,但是finally{}里面改变待返回的值,不会生效。
public class Test{
public static void main(String[] args) {
System.out.println(testFinally());
}
public static int testFinally() {
int b = 20;
try {
System.out.println("try block");
return b += 80;
}catch (Exception e) {
System.out.println("catch block");
}
finally {
System.out.println("finally block");
if (b > 25) {
System.out.println("b>25, b = " + b);
}
b=2000;
}
return b;
}
}
运行结果:
try block
finally block
b>25, b = 100
100
返回值是100,而不是2000,可见在finally里面改变返回结果不会生效。
2.执行finally{}语句块下面的return语句
finally{}在return之前执行,改变待返回的值会生效。即此时代码是顺序执行。
public class Test{
public static void main(String[] args) {
System.out.println(testFinally());
}
public static int testFinally() {
int b = 20;
try {
System.out.println("try block");
}catch (Exception e) {
System.out.println("catch block");
}
finally {
System.out.println("finally block");
if (b > 25) {
System.out.println("b>25, b = " + b);
}
b=2000;
}
return b += 80;
}
}
运行结果:
try block
finally block
2080
输出结果是2080,而不是80,说明finally里面改变待返回的值会生效。
3.finally{}里面有return
如果finally{}语句块里面有return语句,那么finally{}语句块后面的return就不需要了,因为永远不会执行到后面。
public class Test{
public static void main(String[] args) {
System.out.println(testFinally());
}
@SuppressWarnings("finally")
public static int testFinally() {
int b = 20;
try {
System.out.println("try block");
return b += 80;
}catch (Exception e) {
System.out.println("catch block");
}
finally {
System.out.println("finally block");
if (b > 25) {
System.out.println("b>25, b = " + b);
}
b=2000;
return b;
}
}
}
运行结果:
try block
finally block
b>25, b = 100
2000
4.finally{}不会被执行的情况
两种情况下finally语句是不会被执行的:
(1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。
(2)在try块中有System.exit(0);这样的语句,System.exit(0);是终止Java虚拟机JVM的,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。