Java异常类关系图
所有类 都以Throwable为顶层父类
分为2大类
——错误:Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现。
——异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。
进一步将异常分为2大类:非检查异常 检查异常 (根据是否需要javac编译器检查来区分)
——非检查异常 Error 和 RuntimeException 以及他们的子类。
javac在编译时,不会发现这样的异常,不强制要求程序处理这些异常。但可以编写代码处理(使用try…catch…finally)这样的异常,也可以不处理。对于这些异常,我们应该修正代码,而不是去通过异常处理器处理 。非检查异常发生的原因多半是代码编写逻辑问题。
——如除0错误ArithmeticException
——错误的强制类型转换错误ClassCastException
——数组索引越界ArrayIndexOutOfBoundsException
——使用了空对象NullPointerException等等
——检查异常 除了Error 和 RuntimeException的其它异常。
javac强制要求程序员可能发生的这样的异常做预备处理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用throws子句声明抛出它,否则编译不会通过。这样的异常一般是由程序的运行环境导致的。因为程序可能被运行在各种未知的环境下,而程序员无法干预用户如何使用他编写的程序,于是程序员就应该为这样的异常时刻准备着。
——数据库读写出错 SQLException
——输入输出异常IOException
——类加载出错 ClassNotFoundException 等
try catch finally 块是一个典型的异常处理块
try中执行过程可能抛出异常
catch捕获异常 并处理
finally中语句总是会执行
throws关键字
——经典写法 void fun() throws IOException,SQLException{}
——当子类重写父类的带有 throws声明的函数时,其throws声明的异常必须在父类异常的可控范围内——用于处理父类的throws方法的异常处理器,必须也适用于子类的这个带throws方法 。这是为了支持多态。
例如,父类方法throws 的是2个异常,子类就不能throws 3个及以上的异常。父类throws IOException,子类就必须throws IOException或者IOException的子类。
public class Exception_Test {
public static void main(String[] args)
{
Father[] objs = new Father[2];
objs[0] = new Father();
objs[1] = new Son();
for(Father obj:objs)
{
//因为Son类抛出的实质是SQLException,而IOException无法处理它。
//那么这里的try。。catch就不能处理Son中的异常。
//多态就不能实现了。
try
{
obj.start();
}catch(IOException)
{
//处理IOException
}
}
}
}
class Father
{
public void start() throws IOException
{
throw new IOException();
}
}
class Son extends Father
{
public void start() throws Exception
{
throw new SQLException();
}
}
finally块和return
try块中即便有return,break,continue等改变执行流的语句,finally也会执行。
try…catch…finally中的return 只要能执行,就都执行了,
他们共同向同一个内存地址(假设地址是0×80)写入返回值,
后执行的将覆盖先执行的数据,而真正被调用者取的返回值就是最后一次写入的。
finally中的return 会覆盖 try 或者catch中的返回值。
案例演示:
public static void main(String[] args)
{
int result;
result = foo();
System.out.println(result); /2
result = bar();
System.out.println(result); /2
}
public static int foo()
{
try{
int a = 5 / 0;
} catch (Exception e){
return 1;
} finally{
return 2;
}
}
public static int bar()
{
try {
return 1;
}finally {
return 2;
}
}
最终的返回值是Finally中的return