首页 > 代码库 > 第10章-异常处理 --- Checked异常和Runtime异常体系

第10章-异常处理 --- Checked异常和Runtime异常体系

第10章-异常处理 --- Checked异常和Runtime异常体系

  Java的异常被分为两大类:Checked异常和Runtime异常(运行时异常).所有的RuntimeException类及其子类的实例被称为Runtime异常;不是RuntimeException类及其子类的异常实例则被称为Checked异常.

  对于Checked异常的处理方法有如下两种:

  (1)当前方法明确知道如何处理该异常,程序应该用try...catch块来捕获该异常,然后在对应的catch块中修复该异常.

  (2)当前方法不知道如何处理这种异常,应该在定义该方法时声明抛出该异常.

 

(一)使用throws声明抛出异常

  使用throws声明抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理;如果main方法也不知道如何处理这种类型的异常,也可以使用throws声明抛出异常,该异常将交给JVM处理. JVM对异常的处理方法是,打印异常的跟踪栈信息,并中止程序运行。

  throws声明抛出只能在方法签名中使用,throws可以声明抛出多个异常类,多个异常类之间以逗号隔开。

  throws声明抛出的语法格式如下:

    throws ExceptionClass1,ExceptionClass2...

  上面throws声明抛出的语法格式仅跟在方法签名之后,一旦使用throws语句声明抛出该异常,程序就无须使用try...catch块来捕获该异常了.

import java.io.FileInputStream;
import java.io.IOException;

public class ThrowsTest
{
    public static void main(String[] args) throws IOException
    {
        FileInputStream fis = new FileInputStream("a.txt");
    }
}

 

 

 

  上面程序声明不处理IOException异常,将该异常交给JVM处理,所以程序一旦遇到该异常,JVM就会打印该异常的跟踪栈信息,并结束程序.

---------------------------------------------------------------------------------------------- 

(注:如果某段代码中调用了一个带throws声明的方法,该方法声明抛出了Checked异常,则表明该方法希望它的调用者来处理该异常.也就是说,调用该方法时要么放在try块中显示捕获该异常,要么放在另一个带throws声明抛出的方法中)

  下面举例:  

import java.io.FileInputStream;
import java.io.IOException;

public class ThrowsTest2
{
    public static void main(String[] args) throws Exception
    {
        //因为test()方法声明抛出IOException异常
        //所以调用该方法的代码要么处于try...catch块中
        //要么处于另一个带throws声明抛出的方法中
        test();
    }
    
    public static void test() throws IOException
    {
        //因为FileInputStream的构造器声明抛出IOException异常
        //所以调用FileInputStream的代码要么处于try...catch块中
        //要么处于另一个带throws声明抛出的方法中
        FileInputStream fis = new FileInputStream("a.txt");
    }
}

 ------------------------------------------------------------------------------------------------------

 使用throws声明抛出异常时有一个限制,就是方法重写时"两小"中的一条规则:子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同,子类方法声明抛出的异常不允许比父类方法声明抛出的异常多.

 下面举例:

import java.io.FileInputStream;
import java.io.IOException;

public class OverrideThrows
{
    public void test() throws IOException
    {
        FileInputStream fis = new FileInputStream("a.txt");
    }
}

class Sub extends OverrideThrows
{
    //子类方法声明抛出了比父类方法更大的异常
    //所以下面的方法出错
    @Override
    public void test() throws Exception
    {
        // TODO Auto-generated method stub
        super.test();
    }
}

 

 

 

 上面程序中Sub子类中的test()方法声明抛出Exception,该Exception是其父类声明抛出异常IOException类的父类,这将导致程序无法通过编译.

由此可见,使用Checked异常至少存在如下两大不便之处:

(1)对于程序中Checked异常,Java要求必须显示捕获并处理该异常,或者显示声明抛出该异常.这样就增加了编程的复杂度

(2)如果在方法中显示声明抛出Checked异常,将会导致方法签名与异常耦合,如果该方法是重写父类的方法,则该方法抛出的异常还会受到被重写方法所抛出异常的限制.