【黑马程序员】Java异常处理

时间:2022-11-25 00:45:18

【黑马程序员】Java异常处理 -------android培训java培训、期待与您交流! ----------

       Java是一门成熟的编程语言,提供了完善的异常处理机制。Java的异常处理主要依赖try、catch、finally、throw、throws这5个关键字。

其中try块后紧跟花括号构成try块,用来写可能引发异常的代码;catch后可跟异常类型和代码块构成catch块,主要用来处理该类型的异常;

finally块可放置在catch块后,用于释放在try块中打开的资源。

1.  异常处理机制

        Java的异常处理将业务逻辑代码和错误处理代码分离,提供了更好的可读性。

        Java试用try catch进行异常处理,语法结构如下所示:

try
{
    //业务逻辑代码
}
catch (Exception e)
{
    //异常处理代码
    System.out.println(“程序出错");
}

        抛出异常:当执行try块中的代码出现异常是,系统将创建一个该异常的对象,并提交到Java运行时环境,该过程被称为throw异常。

        捕获异常:当Java运行时环境接受到异常对象后,会寻找能够处理该异常的catch块,如果找到合适的catch块,则将该异常交给该catch异常处理。

        注意:不管执行的程序是否在try中,甚至是catch块中的代码,当出现异常后,系统都会创建该异常的对象。如果程序没有为该异常定义任何的catch块,则该异常无法被处理,Java程序将会退出。

2. 异常类的继承关系

         catch块的寻找方式:当try块中出现异常后,系统将依次判断该异常对象是否属于catch后跟的异常类或其子类,如果是则将异常对象传递给该catch后的异常形参变量,并执行catch块的代码处理异常。

        注意:try块的花括号不能省略;try块中定义的变量是局部变量,catch块中无法使用。

        Java提供了丰富的异常类,这些异常类之间有严格的继承关系,如图所示。

【黑马程序员】Java异常处理

        Java将所有的非正常情况分为两种,异常(Exception)和错误(Error),他们都继承制Throwable父类。

  • Error错误:一般是虚拟机出现问题,例如系统崩溃,虚拟机错误,动态链接失败等。Error错误不可恢复并且不能捕捉,一单出现系统将中断。不能用catch进行捕获。
  • Exception异常:Runtime,SQL等。

        下面是一些简单的异常捕捉例子:

public class DivTest {
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            int c = a / b;
            System.out.println("您输入的两个数相除的结果是:" + c );
        }
        catch (IndexOutOfBoundsException ie) {
            System.out.println("数组越界:运行程序时输入的参数个数不够");
        }
        catch (NumberFormatException ne) {
            System.out.println("数字格式异常:程序只能接受整数参数");
        }
        catch (ArithmeticException ae) {
            System.out.println("算术异常");
        }
        catch (Exception e) {
            System.out.println("未知异常");
        }
    }
}

注意:在异常处理时要记住先处理小异常在处理大异常,将异常子类放在前面。

3. finally块的使用

        finally总会被执行(除非在try块或catch块中执行了退出JVM方法(System.exit())),所以一般用来关闭打开的各种物理资源。

        当程序执行到try或catch中的return或者throw语句时,并不会立即结束方法,而是会寻找是否存在finally块,如果有则先执行finally块中的代码,再执行return或throw语句。如果finally中包含了return语句,那么方法会被介绍,导致try或catch中的return等语句得不到执行,可到导致程序出错。

        示例:

public class FinallyTest
{
    public static void main(String[] args) 
    {
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream("a.txt");
        }
        catch (IOException ioe)
        {
            System.out.println(ioe.getMessage());
            //return语句强制方法返回
            return ;       //①
            //使用exit来退出虚拟机
            //System.exit(1);     //②
        }
        finally
        {
            //关闭磁盘文件,回收资源
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException ioe)
                {
                    ioe.printStackTrace();
                }
            }
            System.out.println("执行finally块里的资源回收!");
        }
    }
}

4. Checked异常和Runtime异常

        Java的异常分为两大类:Checked异常和Runtime异常。

        RuntimeException类及其的子类的实例Runtime异常,除此之外的实例为Checked异常。

        Checked异常必须被显示的处理,处理方法如下:

        ①使用try..catch处理异常

        ②使用throws抛出该异常

5. 使用throws抛出异常:

        使用throws抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理,如果main方法也不知道如何处理这种类型的异常,也可以用throws抛出,将异常交给JVM处理。JVM对异常的处理方式是,打印异常的跟踪栈信息,并中止程序的运行。
        throws只能在方法签名后面使用,可以同时声明抛出多个异常类,多个异常类之间用逗号隔开,其语法格式如下:
        throws ExceptionClass1, ExceptionClass2...
        一旦使用了throws语句声明抛出异常,在方法中就无法通过try..catch块捕获该异常。
        示例:

public class ThrowsTest {
    public static void main(String[] args)
        throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
    }
}
        上面的程序不处理异常,一旦发生异常,JVM会打印异常信息,并结束程序的运行。
        如果某个方法加入了throws的声明,该方法希望他的调用者来处理该异常,如下面的程序所示:
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");
    }
}

6. 使用throw抛出异常

        如果需要在程序中自行抛出异常,则应该使用throw语句,throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常示例,而且每次只能抛出一个异常示例。throw语句的语法格式如下:
        throw ExceptionInstance;
        如果throw抛出的是checked异常,则该throw语句要么处于try块中,要么放在一个带throws声明抛出的方法中。如果抛出的是Runtime类型异常,那么该语句无需放在try块中,方法也不用抛出改异常,交由JVM自行处理。
        示例:
public class ThrowTest {
    public static void main(String[] args) {
        try {
            // 调用声明抛出Checked异常的方法,要么显式捕获该异常
            // 要么在main方法中再次声明抛出
            throwChecked(-3);
        }
        catch (Exception e) {
            System.out.println(e.getMessage());
        }
        // 调用声明抛出Runtime异常的方法既可以显式捕获该异常,
        // 也可不理会该异常
        throwRuntime(3);
    }
    public static void throwChecked(int a)throws Exception {
        if (a > 0) {
            //自行抛出Exception异常
            //该代码必须处于try块里,或处于带throws声明的方法中
            throw new Exception("a的值大于0,不符合要求");
        }
    }
    public static void throwRuntime(int a) {
        if (a > 0) {
            //自行抛出RuntimeException异常,既可以显式捕获该异常
            //也可完全不理会该异常,把该异常交给该方法调用者处理
            throw new RuntimeException("a的值大于0,不符合要求");
        }
    }
}
        通过上述程序可看出,自行抛出Runtime异常比自行抛出Checked类型的灵活性更好。同样,抛出Checked异常让编译器提醒程序员必须处理该异常。