Java中的异常、处理机制和自定义异常

异常

什么是异常?

程序开发和运行过程中会出现编译错误运行错误。编译错误容易被发现并排除,而运行错误(逻辑错误和异常)很难预料。因此为了程序的稳定性和可靠性,就需要对程序异常处理和保护。

异常( Exception ):正常程序流程所不能处理或者没有处理的异常情况或异常事件。

一、异常样例

public class DemoException {
    public static void main(String[] args) {
        String.out.println(5/0);
    }
}

运行结果:
异常样例

二、异常的结构

异常结构

  • Error是程序中无法处理的错误,表示运行应用程序中出现了严重的错误,表示代码运行时 JVM 出现问题。Error不能被程序员通过代码处理,Error很少出现,因此程序员应该关注Exception为父类的分支下的各种异常类。
  • Exception程序本身可以捕获并且可以处理的异常。
    • 非运行时异常:编译器会检查出此类异常,如果程序中出现此类异常,如IOException,必须对该异常进行处理,使用try-catch捕获,或者使用throws抛出,否则编译不能通过。
    • 运行时异常:此类异常属于不可查异常,一般是有程序逻辑错误引起的,在程序中可以选择抛出捕获处理,也可以不处理。
    • 常见异常:
      • 输入输出异常:IOException
      • 文件未找到异常:FileNotFoundException
      • 算术异常:ArithmeticException
      • 空指针异常:NullPointException
      • 数组下标越界异常:ArrayIndexOutOfBoundsException
      • 类型强制转换异常:ClassCastException
      • 操作数据库异常:SQLException

三、异常处理机制

在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。

抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。

捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。

一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。

一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。

3.1 抛出异常

  • throw抛出异常

    throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,后面的语句执行不到。抛出的异常会等待捕获。

    例子:

    public class DemoException {
        public static void main(String[] args) {
            int a = 5;
            int b = 0;
            if (b == 0) {
                throw new ArithmeticException("除数不能为0");
            }
            System.out.println(a/b);
        }
    }
    

    运行结果:
    异常1

    throw抛出的异常,会在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。

  • throws抛出异常

    throws一般声明在方法上。如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常,交给方法的调用者进行处理,方法的调用者也可以选择继续用throws抛出。

    throws语句用在方法定义时声明该方法要抛出的异常类型,如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。

    例子:

    public class DemoException {
        public static void main(String[] args) throws FileNotFoundException {
            fileUpload();
        }
        public static void fileUpload() throws FileNotFoundException {
            FileInputStream fileInputStream = new FileInputStream("a.txt");
        }
    }
    

    运行结果:
    异常2

3.2 捕获异常

  • try-catch捕获异常

    在Java中,异常通过try-catch语句捕获。

    try {
        // 可能会发生异常的程序代码
        // 不发生异常,则忽略catch,继续执行
        // 发生异常,则尝试匹配catch
    } catch (Type1 id1){
        // 捕获并处置try抛出的异常类型Type1
        // 可通过printStackTrace()抛出具体异常
        // 也可自定义异常处理信息
    }
    catch (Type2 id2){
         //捕获并处置try抛出的异常类型Type2
    }
    // 一个try至少带一个catch
    

    例子:

    public class DemoException {
        public static void main(String[] args) {
            try {
                System.out.println(5/0);
            }catch (Exception e) {
                //e.printStackTrace();
                System.out.println("除数不能为0");
            }
        }
    }
    

    运行结果:

异常3

  • finally关键字

    finally块中的代码,无论有无异常最终都会执行。

    finally常用于清理或者关闭资源工作,如数据库连接的关闭、lock锁的unlock等。

    try {
    	// 可能会发生异常的程序代码
    } catch (Type1 id1) {
    	// 捕获并处理try抛出的异常类型Type1
    } catch (Type2 id2) {
    	// 捕获并处理try抛出的异常类型Type2
    } finally {
    	// 无论是否发生异常,都将执行的语句块
    }
    

    例子:

    public class DemoException {
        public static void main(String[] args) {
            try {
                System.out.println(5/0);
                //System.out.println(5/1);
            }catch (Exception e) {
                System.out.println("除数不能为0");
            }finally {
                System.out.println("最终都会执行");
            }
        }
    }
    

    异常4
    异常5

四、自定义异常

jdk本身提供了足够多的异常,一般不需要自定义异常,仅作了解。

jdk提供的异常类编写步骤:

自定义异常

自定义异常类:

public class MyException extends Exception {
    private int number;

    public MyException(int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "MyException: (除数不能为0) number = " + number;
    }
}

测试异常类:

public class Test {
    public static void main(String[] args) {
        try {
            division(5,0);
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
    public static int division(int a, int b) throws MyException {
        int result = 0;
        if (b == 0) {
            throw new MyException(b);
        }else {
            result = a / b;
        }
        return result;
    }
}

运行结果:

异常6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值