Java - 异常

1. 异常类型

五个关键字:
trycatchfinallythrowthrows

在这里插入图片描述

 

2. 抛出和捕获异常

快捷键:Ctrl + Alt + T

在这里插入图片描述

 

2.1 try 和 catch

import java.util.Random;

class HandleError {
    public static void main(String[] args) {
        int a=0, b=0, c=0;
        Random r = new Random();

        for (int i = 0; i < 32000; i++) {
            try {  // try 监控区域
                // 生成随机有效整数(不带参数则没有范围)
                b = r.nextInt();
                c = r.nextInt();
                a = 12345 / (b/c);
            } catch (ArithmeticException e) {// catch(想要捕获的异常类型) 捕获异常
                // 显示异常的描述信息
                System.out.println("Exception: " + e);
                a = 0;    // 将 a 置为0,继续
            }
            System.out.println("a: " + a);
        }
    }
}
Output:
a: 12345
Exception: java.lang.ArithmeticException: / by zero
a: 0
Exception: java.lang.ArithmeticException: / by zero
a: 0
Exception: java.lang.ArithmeticException: / by zero
a: 0
a: -12345
a: -726
a: 12345
...

 

2.2 多条 catch 子句

有些情况下,单块代码可能会引发多个异常

package com.feiye.Demo02;

class MultipleCatches {
    public static void main(String[] args) {
        try {
            int a = args.length;
            System.out.println("a = " + a);
            int b = 42 / a;
            int[] c = {1};
            c[42] = 99;
        } catch (ArithmeticException e) {
            System.out.println("Divide by 0: " + e);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array index oob: " + e);
        }
        System.out.println("After try/catch blocks...");
    }
}
Output1:
a = 0
Divide by 0: java.lang.ArithmeticException: / by zero
After try/catch blocks...

Output2:
在这里插入图片描述

注:

  • 异常子类必须位于其所有超类之前,因为使用了某个超类的catch语句会捕获这个超类及其所有子类的异常**(先小后大)**
public class SuperSubCatch {
    public static void main(String[] args) {
        try {
            int a = 0;
            int b = 42 / a;
        } catch (Exception e) {
            System.out.println("Generic Exception catch.");
        }
        // 以下语句报错!!
        catch (ArithmeticException e) {
            System.out.println("这条语句不会到达,ArithmeticException已经在Exception中被捕获");
        }
    }
}

更换两条catch即可:

package com.feiye.Demo03;

public class SuperSubCatch {
    public static void main(String[] args) {
        try {
            int a = 0;
            int b = 42 / a;
        }
        catch (ArithmeticException e) {
            System.out.println("ArithmeticException: " + e);
        }
        catch (Exception e) {
            System.out.println("Exception: " + e);
        }
    }
}

 

2.3 嵌套的 try 语句

class NestTry {
    public static void main(String[] args) {
        try {
            int a = args.length;
            int b = 42 / a;

            System.out.println("a = " + a);

            // 嵌套 try
            try {
                if (a==1)
                    a=a/(a-a);
                if (a==2) {
                    int[] c = {1};
                    c[42] = 99;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("Array index out-of-bounds: " + e);
            }
        } catch (ArithmeticException e) {
            System.out.println("Divide by 0: " + e);
        }
    }
}

Output:

在这里插入图片描述

 

2.4 主动抛出异常 throw throws

  1. throw
class ThrowDemo {
    static void demoproc() {
        try {
            throw new NullPointerException("demo");
        } catch (NullPointerException e) {
            System.out.println("捕获内部 demoproc.");
            throw e;   // 重新抛出异常
        }
    }
    public static void main(String[] args) {
        try {
            demoproc();
        } catch (NullPointerException e) {
            System.out.println("重新捕获: " + e);
        }
    }
}
Output:
捕获内部 demoproc.
重新捕获: java.lang.NullPointerException: demo
  • throw 语句之后的执行流会立即停止,所有后续语句都不会执行
  1. throws
class ThrowsDemo {
    static void throwOne() throws IllegalAccessException {
        System.out.println("throwOne内部");
        throw new IllegalAccessException("demo");
    }

    public static void main(String[] args) {
        try {
            throwOne();
        } catch (IllegalAccessException e) {
            System.out.println("捕获: " + e);
        }
    }
}
Output:
throwOne内部
捕获: java.lang.IllegalAccessException: demo
public class Test {
    public static void main(String[] args) {
        try {
            new Test().test(1, 0);
        } catch (ArithmeticException e) {
            System.out.println("捕获: " + e);
        }
    }

    // 假设在方法中处理不了这个异常,就在方法中抛出异常
    public void test(int a, int b) throws ArithmeticException{
        if (b == 0) { // 主动抛出异常 throw throws, 一般在方法中使用
            throw new ArithmeticException("除数不能为0");
        }
        System.out.println(a / b);
    }
}
Output:
捕获: java.lang.ArithmeticException: 除数不能为0

 

2.5 finally

class FinallyDemo {
    static void procA() {
        try {
            System.out.println("procA内部");
            throw new RuntimeException("demo");
        } finally {
            System.out.println("procA's finally");
        }
    }

    static void procB() {
        try {
            System.out.println("procB内部");
            return;
        } finally {
            System.out.println("procB's finally");
        }
    }

    static void procC() {
        try {
            System.out.println("procC内部");
        } finally {
            System.out.println("procC's finally");
        }
    }

    public static void main(String[] args) {
        try {
            procA();
        } catch (Exception e) {
            System.out.println("捕获异常");
        }
        procB();
        procC();
    }
}
Output:
procA内部
procA's finally
捕获异常
procB内部
procB's finally
procC内部
procC's finally

如果finally代码块和某个try代码块相关联,那么finally代码块会在这个try代码块结束后执行

 

3. 自定义异常

MyException.java

package oop.Demo13;

// 自定义的异常类
public class MyException extends Exception{
    // 传递数字 > 10
    private int detail;

    public MyException(int a) {
        this.detail = a;
    }

    // toString: 异常的打印信息

    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}

Test.java

package oop.Demo13;

public class Test {
    // 可能会存在异常的方法
    static void test(int a) throws MyException{
        System.out.println("传递的参数为: " + a);

        if (a > 10) {
            throw new MyException(a);
        }

        System.out.println("OK");
    }

    public static void main(String[] args) {
        try {
            test(11);
        } catch (MyException e) {
            // 增加一些处理异常的代码
            System.out.println("MyException -> " + e);
        }
    }
}
Output:
传递的参数为: 11
MyException -> MyException{detail=11}

Throwable 定义的方法

方法描述
final void addSuppressed(Throwable exc)将exc添加到与调用异常关联的suppressed异常列表中,主要用于新的带资源的try语句
Throwable fillInStackTrace()返回一个包含完整堆栈踪迹的Throwable对象,可重新抛出该对象
Throwable getCause()返回引起当前异常的异常。如果不存在引起当前异常的异常,就返回null
String getLocalizedMessage()返回异常的本地化描述信息
String getMessage()返回异常的描述信息
StackTraceElement[] getStackTrace()返回一个包含堆栈踪迹的数组,数组元素的类型为StackTraceElement,每次一个元素。堆栈顶部的方法是抛出异常之前调用的最后一个方法,可以在数组的第一个元素中找到该方法。通过StackTraceElement类,程序可以访问与踪迹中每个元素相关的信息,如方法名
final Throwable[] getSuppressed()获取与调用异常关联的suppressed异常,并返回一个包含结果的数组。suppressed异常主要由带资源的try语句生成
Throwable initCause(Throwable causeExc)将causeExc与调用异常关联到一起,作为调用异常的原因。返回对异常的引用
void printStackTrace()显示堆栈踪迹
void printStackTrace(PrintStream stream)将堆栈踪迹发送到指定的流中
void setStackTrace(StackTraceElement[] elements)将elements中传递的元素设置为堆栈踪迹。该方法用于特殊的应用程序,在常规情况下不使用
String toString()返回包含异常描述信息的String对象,当通过println()输出Throwable对象时,会调用该方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值