一、异常分类
一般分为运行时异常(CheckedException)和非运行时异常(RuntimeException)。
二、CheckedException和RuntimeException
1、CheckedException
对CheckedException处理方法有两种:
1)当前方法知道如何处理,用try…catch来处理该异常。
2) 当前方法不知道如何处理,则在定义该方法时声明抛出该异常。
比较熟悉的checkedException有:
1)java.lang.ClassNotFoundException
找不到指定类异常;
2)java.lang.NoSuchMethodException
找不到方法异常;
3)java.io.IOException
操作输入和输出流可能出现的异常;
2、RuntimeException
我们比较熟悉的RuntimeExceptiond类的子类有:
1)java.lang.ArithmeticException
算术条件异常,如:数字除零;
2)java.lang.ArrayStoreException
数组包含不兼容的值抛出的异常
3)java.io.ClassCastException
类型转换异常;
4) java.lang.IndexOutOfBoundsException
下标索引越界异常;
5) java.lang.NullPointerException
空指针异常;
6) java.lang.IllegalArgumentException
非法参数异常;
三、Try、Catch和Finally
1、Try
Try后面大括号里面的代码,称为监控区域,我们首先把可能抛出异常的代码放在监控区域。如果在运行过程中出现异常,则创建异常对象,将异常抛出监控区域之外。
2、Catch
Try抛出的异常,系统会匹配到catch语句以捕获。所谓匹配就是看能否将抛出的异常对象赋值给参数中异常类型的变量。执行完匹配的catch语句之后,其他catch语句就会被忽略掉。所以catch语句必须子类在前,父类在后。
Catch非常有用,从简单方面可以输出信息,或提醒用户做出决定,甚至使用链式异常将异常传递给更高一级的异常处理程序。
关于catch需要注意:
1)参数的异常类型必须是Throwable类或其子类。
2)从上往下的catch语句,其参数类型必须按照先子类后父类顺序,因为一旦匹配到一个类型,catch语句捕获这个超类及其所有子类的异常,就会忽略后面的catch,也就意味着排在后面的子类用于不会到达,程序是会进行报错的。
3)可以有一个或者多个catch语句,甚至如果有finally语句的情况下,可以没有catch语句。
3、Finally
finally中的代码总是会被执行
小结:
try块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
catch块:用于处理try捕获到的异常。
finally块:无论是否捕获或处理异常,finally块里的语句都会被执行。
当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:
1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。
四、Throw和Throws
1、Throw
Throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。
2、Throws
如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。
Throws抛出异常的规则:
1) 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。
2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现受可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误
3)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。
4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。