java异常的捕获与处理(上)

一、认识异常

在开发的过程中,有时程序出现的不可避免,不可预测的错误发生,我们称之为异常,异常一旦你出现并没有进行合理处理的话,那么程序就将中断进行。

范例1(没有异常的程序):

public class TestDemo {
    public static void main(String[]args){
        System.out.println("除法");
        int result = 10/2;
        System.out.println("计算结果:"+result);
        System.out.println("计算结束");
    }
}

运行结果:

除法
计算结果:5
计算结束

范例2(产生异常的程序):

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/5/29 20:48
 */

public class TestDemo {
    public static void main(String[]args){
        System.out.println("除法");
        int result = 10/0;
        System.out.println("计算结果:"+result);
        System.out.println("计算结束");
    }
}

运行结果:

除法
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.wfg.demo.TestDemo.main(TestDemo.java:11)

对比上述两个范例,可以发现,异常语句一旦产生,之后的语句将不再执行,默认情况下是将异常信息输出,而后自动结束程序的执行。

而我们要做的是:即使程序出现了异常,也要程序正确的执行完毕。所以就引入了异常处理

二、异常的处理

1、try...catch...finally语句

语法格式如下:

try {
            可能出现异常的语句;
        }[catch (异常类型 异常对象){
            处理异常;
        }] [finally {
            程序块(finally语句块是异常处理结构最后执行的部分,无论try如何退出
                    都将执行此语句块);
        }]

范例1(异常处理):

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/5/29 20:48
 */

public class TestDemo {
    public static void main(String[]args){
        System.out.println("除法");
        try {
            int result = 10/0;
            System.out.println("计算结果:"+result);
        } catch (ArithmeticException e) {
            System.out.println(e);
        }
        System.out.println("计算结束");
    }
}

运行结果:

除法
java.lang.ArithmeticException: / by zero
计算结束

分析上例,加入了异常处理后,程序即使有了异常,程序也可以正常的执行完毕,但是异常处理时的错误输出信息和之前对比,出错的信息不明确了,那么为了让错误信息更加的完整,一般会调用printStackTrace()方法进行异常的打印,以下方法的打印的异常信息是最完整的

范例2(printStackTrace方法打印完整错误信息):

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/5/29 20:48
 */

public class TestDemo {
    public static void main(String[]args){
        System.out.println("除法");
        try {
            int result = 10/0; //异常
            System.out.println("计算结果:"+result); //之前语句有异常,此句不在执行
        } catch (ArithmeticException e) {
            e.printStackTrace();   //异常处理:输出错误信息
        }
        System.out.println("计算结束");
    }
}

运行结果:

除法
计算结束
java.lang.ArithmeticException: / by zero
	at com.wfg.demo.TestDemo.main(TestDemo.java:12)

除了try...catch格式处理异常外,还可以使用try...catch...finally:

范例3(异常处理):

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/5/29 20:48
 */


public class TestDemo {
    public static void main(String[]args){
        System.out.println("除法");
        try {
            int result = 10/0;
            System.out.println("计算结果:"+result);
        } catch (ArithmeticException e) {
            System.out.println(e);
        }finally {
            System.out.println("不管出不出现异常都执行");
        }
        System.out.println("计算结束");
    }
}

运行结果:

除法
java.lang.ArithmeticException: / by zero
不管出不出现异常都执行
计算结束

以上例子所执行的数学运算,两个参数都是由程序默认提供,那么如果说现在计算的两个参数都是通过初始化参数传递,会不会出现问题呢?

范例4:

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/5/29 20:48
 */

public class TestDemo {
    public static void main(String[]args) {
        System.out.println("除法");
        try {
            int x = Integer.parseInt(args[0]); //接收参数
            int y = Integer.parseInt(args[1]);//接收参数
            int result = x/y;
            System.out.println("计算结果"+result);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } finally {
            System.out.println("不管是否出现异常都执行");
        }
        System.out.println("计算结束");
    }
}

运行结果:
 

除法
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
不管是否出现异常都执行
	at com.wfg.demo.TestDemo.main(TestDemo.java:13)

分析以上例子:

数据由外部传送,那么就有可能出现以下问题:
(1)执行时不输入参数,ArrayIndexOutOfBoundsException,未处理;

(2)输入的参数不是数字,NumberFormatException,未处理;

(3)被除数为0,ArithmeticException,已处理。

可以发现,以上的程序实际上是存在三种异常,而程序中只能处理一种,而对于不能处理的异常,发现程序会直接中断执行。我们可以通过添加多个catch的方法来解决此类问题。

范例4(加入多个catch):

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/5/29 20:48
 */

public class TestDemo {
    public static void main(String[]args) {
        System.out.println("除法");
        try {
            int x = Integer.parseInt(args[0]); //接收参数
            int y = Integer.parseInt(args[1]);//接收参数
            int result = x/y;
            System.out.println("计算结果"+result);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        finally {
            System.out.println("不管是否出现异常都执行");
        }
        System.out.println("计算结束");
    }
}

三、异常处理流程

上面已经完成了异常的基本处理,但是所有的异常像之前那样添加多个catch一条条的判断似乎是不可能的任务,因为我们今后可能会碰见各种各样的异常,包括很多没有见过的异常。所以我们必须研究异常的流程和结构。

查看两个异常类的继承结构:

(1)ArithmeticException:
java异常的捕获与处理(上)_第1张图片

(2)ArrIndexOutOfBoundException:

java异常的捕获与处理(上)_第2张图片

可以发现,所有的异常类型最高的继承类是Throwable,Throwable下有两个子类:

(1)Error:指的是·JVM错误,这个时候的程序并没有执行,无法处理;(少见)

(2)Exception:指的是程序中出现的错误信息,可以进行异常处理。(RuntimeException就是一个常见的错误可catch可不catch,属于编程导致的错误,比如:数组访问越界、访问空指针等等)

java异常的捕获与处理(上)_第3张图片

通过继承关系发现,在进行处理异常的时候以Exception为主,并且可以进行以下的异常处理流程:

java异常的捕获与处理(上)_第4张图片

1、如果程序发生了异常,那么JVM根据异常的类型,实例化一个指定的异常类的对象;

2、如果这时候程序中没有任何的异常处理操作,则这个异常的实例化对象将交给JVM进行处理,而JVM的默认处理方式就是进行异常信息的输出,而后中断程序;

3、如果程序存在了异常处理,则会由try语句捕获产生的异常对象;

4、与try之后的每一个catch进行匹配,如果匹配成功,则使用指定的catch进行处理,如果没有匹配成功,则向后面的catch继续匹配,如果没有任何的catch匹配成功,则这个时候交给JVM进行默认处理;

5、不管是否有异常都会执行finally程序,如果此时没有异常,执行完finally,则会执行程序之中其他代码,如果此时有异常没能够处理(没一个catch可以满足),那么也会执行finally,但执行完finally后,将默认交给JVM进行异常信息的输出,并且程序中断。

通过上面的分析可以发现。实际上catch捕获异常类型的操作,就和方法接收参数是一样的,从多态角度来讲,所有的异常都是Exception的子类,那么实际上所有的异常都可以使用Exception进行接收:

范例:

package com.wfg.demo;

/**
 * @Author WFG
 * @Date 2019/5/29 20:48
 */

public class TestDemo {
    public static void main(String[]args) {
        System.out.println("除法");
        try {
            int x = Integer.parseInt(args[0]); //接收参数
            int y = Integer.parseInt(args[1]);//接收参数
            int result = x/y;
            System.out.println("计算结果"+result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            System.out.println("不管是否出现异常都执行");
        }
        System.out.println("计算结束");
    }
}

但这种操作也存在一些问题:如果在一些异常处理要求严格的项目中,异常必须分别处理,这时Exception就不是那么好用了。

如果异常处理不是很严格直接编写Exception即可。

 

 

你可能感兴趣的:(JAVA学习)