2MUCH

异常的处理

2022-06-04


异常的处理

分类

异常的层次

Exception和Error都继承自Throwable类。层次图可见下图(列出主要的异常类)

img

常见内置异常类

Java 语言定义了一些异常类在 java.lang 标准包中。主要分类可见 https://www.runoob.com/java/java-exceptions.html#/

或者链接 https://blog.csdn.net/Pandafz1997/article/details/119898686#/ 给出的:

异常类 说明 ClassCastException 类型转换异常 ArrayIndexOutOfBoundsException 数组越界异常 NegativeArraySizeException 指定数组维数为负值异常 ArithmeticException 算数异常 InternalException Java系统内部异常 NullPointerException 空指针异常 IllegalAccessException 类定义不明确所产生的异常 IOException 一般情况下不能完成I/O操作产生的异常 EOFException 打开文件没有数据可以读取的异常 FileNotFoundException 在文件系统中找不到文件路径或文件名称时的异常 ClassNotFoundException 找不到类或接口所产生的异常 CloneNotSupportedException 使用对象的clone方法但无法执行Cloneable所产生的异常

异常处理

方法1:捕获处理

try+catch(+finally)

try {
    xxx; //程序
} catch (ExceptionName e) {
    xxx; //捕获异常时的处理
} finally {
    xxx; //最终执行的代码块
}

若指定捕获特定的异常类,则在catch中指定异常类;若要捕获任意异常,则直接用Exception e

finally不是必须的,包含无论是否发生异常都会被执行到的代码块(一般包含清理类型等收尾善后性质的语句)。

有4种特殊情况,finally块不会被执行:

需要注意的是,就算try块中有return,也会先执行完finally再return。

当try中抛出异常且catch中有return语句,finally中没有return语句,java先执行catch中非return语句,再执行finally语句,最后执行return语句。若try中没有抛出异常,则程序不会执行catch体里面的语句,java先执行try中非return语句,再执行finally语句,最后再执行try中的return语句。

但是:finally中有return时,会覆盖掉try和catch中的return。

如果finally中定义的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块中之前保存的值;如果finally中定义的数据是是引用类型,则finally中的语句会起作用,try中return语句的值就是在finally中改变后该属性的值。

以上举例见:https://blog.csdn.net/Pandafz1997/article/details/119898686#/

try不能单独存在,必须跟上catch或finally。

多重捕获

try {
    xxx; //程序
} catch (ExceptionName1 e) {
    xxx; //捕获异常1时的处理
} catch (ExceptionName2 e) {
    xxx; //捕获异常2时的处理
}

执行逻辑:依次匹配异常,当匹配到该异常或尝试匹配完所有异常后,停止匹配。

通常,为捕获到所有可能出现的异常,可以在处理异常的末尾,加上Exception 类,这样即可以使所有异常都被捕捉到,也可以防止想捕获具体异常时被它提前捕获。

方法2:抛出异常

throw(用于抛出异常),throws(用在方法签名中,用于声明该方法可能抛出的异常)

public void fun() throws ExceptionName1, ExceptionName2 {
    xxx; //可能抛出异常的代码块
}

若指定抛出特定的异常类,则在throws后面指定异常类;若要抛出任意异常,则直接用Exception。可抛出多个异常类,用逗号隔开(如上)。

若要在执行代码块中手动抛出异常,格式为:throw new 异常类名(参数);通常用于抛出自定义的异常类

public void fun() throws ArithmeticException {
    throw new ArithmeticException("异常信息:除数不能为0");//抛出具体问题,编译时不检测
}

throw在方法体中,程序会在throw语句后立即终止,它后面的语句执行不到(后面的语句写了也会编译不通过)。

try+catch(+finally) 和 throw 并不是互斥的,两者可以结合使用。例如:

try {
    xxx;
    throw new ExceptionName1("eMessage");
} catch ....

可以在finally语句块中有return语句,finally语句可以让throw和return共存。

注意:调用方法必须遵循一个原则:若覆盖一个方法,则不能声明与覆盖方法不同的异常,声明的任何异常必须是被覆盖方法所声明异常的同类或子类。如下例子(https://blog.csdn.net/Pandafz1997/article/details/119898686#/):

public class Example6_3 {
    void method1() throws IOException {
    }//合法

    //编译错误,必须捕获或声明抛出IOException
    void method2() {
        method1();
    }

  	//编译错误,必须捕获或声明抛出IOException或其父类
    void method3() throws IOError {
        method1();
    }

    //合法,声明抛出IOException
    void method3() throws IOException {
        method1();
    }

    //合法,声明抛出Exception,Exception是IOException的父类
    void method4() throws Exception {
        method1();
    }

    //合法,捕获IOException
    void method5() {
        try {
            method1();
        }catch (IOException e){
            
        }
    }
    
    //编译错误,必须捕获或声明抛出Exception
    void method6() {
        try {
            method1();
        }catch (IOException e){
            throw new Exception();
        }
    }

    //合法,声明抛出Exception
    void method7() throws Exception {
        try {
            method1();
        }catch (IOException e){
            throw new Exception();
        }
    }
}

常用方法

1 public String getMessage() 返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。
2 public Throwable getCause() 返回一个 Throwable 对象代表异常原因。
3 public String toString() 返回此 Throwable 的简短描述。
4 public void printStackTrace() 将此 Throwable 及其回溯打印到标准错误流。。
5 public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。
6 public Throwable fillInStackTrace() 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。

自定义异常

Try-With-Resources

参考链接

https://blog.csdn.net/Pandafz1997/article/details/119898686#/

https://www.runoob.com/java/java-exceptions.html#/

https://blog.csdn.net/java_cxrs/article/details/91661623#/