1.异常的分类
Java的异常处理主要通过Throwable这个类实现的,Throwable又分为Error和Exception两大类。
Error:程序没有办法处理的错误,类似于内存溢出这种错误。
Exception:程序可以通过一些手段恢复的异常。
2.异常的继承
一般自定义异常只需继承Exception类即可。Exception类中有多个构造方法,简单一点的是子类中调用Exception(String name)这个方法来构造父类。
3.异常的抛出
一般在写一个方法时,如果方法体的代码可能发生“意料之中”的错误,我们就可以在方法的定义处加上抛出异常的描述,以告诉使用它的方法不要忘记处理这些异常。
public void throwException1() throws Execption {
....
}
4.不必声明的异常
也有些异常不需要在方法声明时抛出,Error类及其子类和RuntimeException类及其子类可以不在方法定义时声明。因为这两个异常都是我们在编写代码是无法预料到的。除了这两个类型的异常之外的所有异常都要在方法定义处声明。
public void runtimeException1() {
throw RuntimeException();
}
5.抛异常方法的继承
假设父类的一个方法声明抛出三个异常,那么子类覆盖该方法时只能抛出这三个方法的子集,也可以抛出父类声明抛出的异常的子类。以便在多态编程时父类的异常处理能够涵盖所有的子类。
class Father {
public void m1() throws Exception, IOException{}
}
class Son1 extends Father{
@Override
public void m1() throws IOException {}
}
class Son2 extends Father{
//此处的SQLException是Exception的子类
@Override
public void m1() throws SQLException {}
}
这里有一个特殊情况,如果一个接口继承两个父接口,这两个父类接口中定义两个相同的方法。这是在子接口中只能抛出两个父接口方法中共有的异常。
interface A {
void m1() throws IOException, SQLException;
}
interface B {
void m1() throws IOException, TimeoutException;
}
interface C extends A,B {
//只能声明抛出A,B类中m1方法的共有的异常
void m1() throws IOException;
}
这种情况在一个类实现多个接口时也适用。
6.异常的处理
使用try,catch,finally异常处理语法处理流程。如果try块中的代码发生异常,就不在执行try块中剩下的代码,直接跳到catch代码块中执行。如果try块代码安全执行完毕,catch块中代码不执行。无论是否执行catch块代码。finally块中的代码的一定会被执行。
public class ExceptionTest{
public static void main(String[] args) {
System.out.println(test());
}
public static int test() {
try {
int a = 1 / 0;
return 0;
}catch (Exception e) {
return 1;
}finally {
System.out.println("3");
return 2;
}
}
}
这是一段经典的代码,执行结果是32。
理解这段代码需要对JVM有一定的了解。简单来说,就是try块中的代码出现了异常,然后系统跳到catch块中执行return 1语句。JVM中装有返回值的容器中装的是1。现在执行finally代码块中的代码,先打印了3,又执行return 2语句,JVM把装有返回值的容器中的值改为了2。然后方法返回,打印2。
这段代码中,方法的返回是在catch块中确认下来的,finally只是更改了返回的值。因此是先return后执行finally代码块。