java 异常总结

后续还会继续完善,有错误请指教。

---------------------10.10--------------------------- 

总结

  • 1图异常分类;
  • 5个关键字:Try(可能抛出异常的语句/试图捕获异常)  catch(对try中可能抛出的不同异常类型做处理)  finall(无论是否发生异常都会执行finally)  throw(构造并抛出异常)  throws(声明该方法可能抛出的异常)
  • try、catch、finally、return执行顺序
  • 先捕获小的,再大的
  • 异常和重写的关系

异常概念

Java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。

异常分类

in java.lang.Object--java.lang.Throwable--Error错误、Exception异常(部分异常需程序员显式声明或捕获)

-可查异常和不可查异常

可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。
不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。

如果使用throw在方法体中抛出可查异常,则需要在方法头部声明方法可能抛出的异常类型。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。

-编译异常(可查的异常)和运行异常(不可查的异常)

(1)运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

当出现RuntimeException的时候,我们可以不处理。当出现这样的异常时,总是由虚拟机接管。比如:我们从来没有人去处理过NullPointerException异常,它就是运行时异常,并且这种异常还是最常见的异常之一。 
出现运行时异常后,如果没有捕获处理这个异常(即没有catch),系统会把异常一直往上层抛,一直到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。所以若不对运行时异常进行处理,后果严重,要么是线程中止,要么是主程序终止。 
如果不想终止,则必须捕获所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。


(2)非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。

面对异常的消极措施-抛出异常

(此模块还需要完善添加,通过代码深入理解。自定义的异常暂时没思考

抛出异常有三种形式,一是throw,一个throws,系统自动抛异常。

throw 就是抛出一个实际的异常,并获取这个异常的引用,这个异常会被抛到外部的环境,由外部环境进行处理。

throws是一个异常声明,它声明这个方法可能会抛出一个异常,注意是可能,所以在没有异常的情况下也是可以用throws的,而throws本身的作用也是用来提高程序的健壮性,反过来,如果这个方法的的确确的有一个异常,那么编译器会强制让你加上throws这个异常声明。

1)作用不同: throw用于程序员自行产生并抛出异常; throws用于声明在该方法内抛出了异常

2) 使用的位置不同: throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表的后面,不能单独使用。

3)内容不同: throw抛出一个异常对象,且只能是一个; throws后面跟异常类,而且可以有多个。

面对异常的积极措施-捕获和处理

try语句

catch语句

在catch中声明的异常对象 catch(Exception e)封装了异常事件发送的消息,在catch语句中可使用这些对象e方法获取异常信息。如下:

getMessage(),得到有关异常事件的信息。

printStackTrace(),跟踪异常事件发生时,执行堆栈的内容。

 

JAVA中try、catch、finally带return的执行顺序总结

异常处理中,try、catch、finally的执行顺序是按顺序执行的。即,(1)如果try中没有异常,则顺序为try→finally,如果try中有异常,则顺序为try→catch→finally。且(2)无论出现什么情况,finally块中的内容都要被执行。(解释:在执行return语句之前,会先将返回值(复制一份)存储在一个指定的位置,其次再去执行finally中内容,最后返回之前保存的值。)

但有以下几种特殊情况需要注意:

一般情况:

public class TestFinally {
    public static void main(String[] args) {
        int result = testFinally();
        System.out.println(result);

    }

    static int testFinally(){ //定义为static,否则报错!public不是必须要加的。
        try{
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
           // return 0;
        }finally {
            System.out.println("execute finally");
        }
       return 0; // 若无返回,会报错!或者将返回放在catch中
    }
}
/*输出:
execute finally
1
*/

情况2:finally中改变return的值时,需要考虑返回值类型。若是对基本类型数据修改则不改变其返回值,但是对于引用类型的数据修改,则影响最终返回值。

public class TestFinally {
    public static void main(String[] args) {
        int result1 = testFinally1();
        System.out.println(result1);
        StringBuffer resultRef = testFinally2();
        System.out.println(resultRef);
    }
    static int testFinally1(){ //定义为static,否则报错!
        int result =1;
        try{
            result = 2;
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }finally {
            result = 3;
            System.out.println("execute finally1");
        }
    }
    static StringBuffer testFinally2(){
        StringBuffer s = new StringBuffer("Hello");
        try{
            return s;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }finally {
            s.append("World");
            System.out.println("execute finally2");
        }
    }
}
/*输出:
execute finally1
2
execute finally2
HelloWorld
 */

解释:return返回时不是直接返回变量的值,而是复制一份。

情况3:当finally中有return语句时,将会覆盖函数中其他return语句。即try /catch中的return会失效

public class TestFinally {
    public static void main(String[] args) {
        int result = testFinally();
        System.out.println(result);

    }

    static int testFinally(){ //定义为static,否则报错!
        try{
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;

        }finally {
            System.out.println("execute finally");
            return 3;
        }
    }
}
/*输出:
execute finally
3
 */

情况4:java程序中的finally块,不一定被执行。

(1)try之前就出现异常语句;

(2)try块中强制退出。

public class TestException {
    public static void main(String[] args) {
       // int i = 100/ 0; 
// 系统抛出异常 Exception in thread "main" java.lang.ArithmeticException: / by zero
        try{
           int i = 100/ 0;
            System.out.print(i);
 //System.exit(0); 报错,不执行finally,情况4
        }catch(Exception e){
            System.out.print("出现异常");
           // throw new  RuntimeException();
        }finally{
            System.out.print(2);
        }
        System.out.print(3);
    }
}
/*
输出:出现异常23
 */

若catch到的不同异常类型之间存在继承,则应该先捕获小的异常。

public class TestException2 {
    public static void main(String[] args) {
        String[][] s = new String[5][];
        try{
            s[1][0] = "hello";
            s[1][1] = "你好";
        } catch (Exception e) {
           // e.printStackTrace();
            System.out.println("数组元素没有正确实例化");
        }
        try{
            s[5] = new String[3];
            s[5][1] = "hello";
        } catch (ArrayIndexOutOfBoundsException e1) {
            //e1.printStackTrace();
            System.out.println("有异常发生了");
        }
        catch (Exception e2) { 
//若将此catch块作为第一个catch,则报错:已经抛出异常,因为上面的是Exception的子类异常
            e2.printStackTrace();
            System.out.println("数组下标越界了");
        }
    }
}
/*输出:
数组元素没有正确实例化
有异常发生了
 */

 重写方法需要抛出与原方法所抛出异常类型 一致或者不抛出异常。

常出的面试题-(用于自查)

异常处理的原理是什么

运行时异常和普通异常有什么区别

finally块中的代码什么时候被执行,是不是一定被执行?

常见的5个编译时异常和5个运行时异常?

throw和throws、try/catch的区别?

部分参考链接:https://www.cnblogs.com/diegodu/p/7298882.html

https://www.cnblogs.com/pcheng/p/10968841.html 

https://blog.csdn.net/hjfcgt123/article/details/53349275

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值