Java异常

目录

一,异常的理解

二,Throwable类的常用方法

①try...catch

②三种方法的代码示例

③finally

 三,throw关键字

语法格式:

示例:

四,运行时异常与编译时异常

1.编译时异常

2.运行时异常

五,自定义异常

自定义类示例示例:

案例:

完整代码:


一,异常的理解

写了这么多代码其实对异常已经不陌生了,比如哪个关键字不小心拼写错了,分号不小心漏了,函数传参时漏参、多参等等,这些都是编程的常见异常,针对这种情况, Java语言引入了异常,以异常类的形式对这些非正常情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理

下面是一个很常见的,0作为除数的异常警告

Java异常_第1张图片

从运行结果可以看出,程序发生了算术异常(ArithmeticException),该异常是由于代码第4行的除法运算出现0作除数。异常发生后,程序会立即结束,无法继续向下执行。

上述程序产生的ArithmeticException异常只是Java异常类中的一种,Java提供了大量的异常类,这些类都继承自java.lang.Throwable类。 接下来通过一张图展示Throwable类的继承体系。

Java异常_第2张图片

Throwable有两个直接子类ErrorException,其中,Error代表程序中产生的错误,Exception代表程序中产生的异常。

  • Error类称为错误类,它表示Java程序运行时产生的系统内部错误资源耗尽的错误,这类错误比较严重,仅靠修改程序本身是不能恢复执行的。举一个生活中的例子,在盖楼的过程中因偷工减料,导致大楼坍塌,这就相当于一个Error。例如,使用java命令去运行一个不存在的类就会出现Error错误。
  • Exception类称为异常类,它表示程序本身可以处理的错误,在Java程序中进行的异常处理,都是针对Exception类及其子类的。在Exception类的众多子类中有一个特殊的子类——RuntimeException类,RuntimeException类及其子类用于表示运行时异常。 Exception类的其他子类都用于表示编译时异常。

二,Throwable类的常用方法

Java异常_第3张图片

在使用这三个方法前,先得认识一下try...catch一一异常捕获

①try...catch

语法格式:

try{

//想要捕获异常的程序代码块

}catch(        Exception(或其子类)        e(对象名)        ){

    //对异常的处理

}

在try代码块中编写可能发生异常的Java语句,catch代码块中编写针对异常进行处理的代码。当try代码块中的程序发生了异常,系统会将异常的信息封装成一个异常对象,并将这个对象传递给catch代码块进行处理。catch代码块需要一个参数指明它所能够接收的异常类型,这个参数的类型必须是Exception类或其子类

注意:catch代码块对异常处理完毕后,程序仍会向下执行,而不会终止程序!

②三种方法的代码示例

public class Main {
    public static void main(String[] args) {
        try {
            int res = 4 / 0;
            System.out.println(res);
        } catch (Exception e) {
            System.out.println("返回异常的消息字符串->" + e.getMessage());
            System.out.println("返回异常的简单消息描述->" + e.toString());
            e.printStackTrace();
        }
        System.out.println("我猜代码现在会执行到这里");
    }
}

Java异常_第4张图片

③finally

 在程序中,有时候会希望有些语句无论程序是否发生异常都要执行,这时就可以在try…catch语句后,加一个finally代码块

来看两个示例的对比:

Java异常_第5张图片Java异常_第6张图片

也就是说不论程序是发生异常还是使用return语句结束,finally中的语句都会执行。因此,在程序设计时,通常会使用finally代码块处理完成必须做的事情,如释放系统资源

但是要区别理解的是,finally中的代码块在有一种情况下是不会执行的,那就是在try...catch中执行了System.exit(0)语句。System.exit(0)表示退出当前的Java虚拟机,Java虚拟机停止了,任何代码都不能再执行了!

Java异常_第7张图片

 三,throw关键字

在实际开发中,大部分情况下我们会调用别人编写的方法,但并不知道别人编写的方法是否会发生异常。针对这种情况,Java允许在方法的后面使用throws关键字对外声明该方法有可能发生的异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在自己的程序中对异常进行处理,否则编译无法通过。

语法格式:

修饰符 返回值类型 方法名(参数1,参数2...) throws 异常类1, 异常类2...{

        //方法体...

}

从上述语法格式中可以看出,throws关键字需要写在方法声明的后面,throws后面需要声明方法中发生异常的类型。

示例:

Java异常_第8张图片

 Java异常_第9张图片

在上述代码中,第3行代码调用divide()方法时传入的第二个参数不管是不是0,由于定义divide()方法时声明了抛出异常,调用者在调用divide()方法时就必须进行处理,否则就会发生编译错误。

至于处理办法,其实就是本篇第二大节介绍的try...catch...finally捕获异常并处理

示例代码:

public class Main {
    public static void main(String[] args) {
        try {
            divide(4, 0);
        } catch (Exception e) {
            System.out.println("返回异常的消息字符串->" + e.getMessage());
            System.out.println("返回异常的简单消息描述->" + e.toString());
            e.printStackTrace();
            return;
        } finally {
            System.out.println("catch里面只要没有exit(0),java虚拟机还没结束,finally模块的代码就会执行");
        }
    }


    static int divide(int x, int y) throws Exception {
        int res = x / y;
        return res;
    }
}

Java异常_第10张图片

四,运行时异常与编译时异常

  • 在实际开发中,经常会在程序编译时产生一些异常,这些异常必须要进行处理,这种异常被称为编译时异常,也称为checked异常。
  • 另外还有一种异常是在程序运行时产生的,这种异常即使不编写异常处理代码,依然可以通过编译,因此被称为运行时异常,也称为unchecked异常。

1.编译时异常

在Exception类中,除了RuntimeException类及其子类,Exception的其他子类都是编译时异常。编译时异常的特点是Java编译器会对异常进行检查,如果出现异常就必须对异常进行处理,否则程序无法通过编译。 处理编译时期的异常有两种方式,具体如下: (1)使用try…catch语句对异常进行捕获处理。 (2)使用throws关键字声明抛出异常,调用者对异常进行处理。

2.运行时异常

RuntimeException类及其子类都是运行时异常。运行时异常的特点是Java编译器不会对异常进行检查。也就是说,当程序中出现这类异常时,即使没有使用try..catch语句捕获或使用throws关键字声明抛出,程序也能编译通过。运行时异常一般是由程序中的逻辑错误引起的,在程序运行时无法恢复。

例如,通过数组的角标访问数组的元素时,如果角标超过了数组范围,就会发生运行时异常,代码如下所示:

int[] arr=new int[5];

System.out.println(arr[6]);

在上面的代码中,由于数组arr的length为5,最大角标应为4,当使用arr[6]访问数组中的元素就会发生数组角标越界的异常。

五,自定义异常

JDK中定义了大量的异常类,虽然这些异常类可以描述编程时出现的大部分异常情况,但是在程序开发中有时可能需要描述程序中特有的异常情况

例如,现在设计一个程序进行除法运算,且不允许除数是负数(意思就是假设我们主观地认为负数作为除数是一个异常)

显然Java不认为除数作为负数是异常,这时候就需要自定义一个异常类,但自定义的异常类必须继承自Exception或其子类。

自定义类示例:

(涉及前面继承的知识点,可移步专栏查找观看->传送门):

Java异常_第11张图片

在实际开发中,如果没有特殊的要求,自定义的异常类只需继承Exception类,在构造方法中使用super()语句调用Exception的构造方法即可。

案例:

Java异常_第12张图片

从运行结果可以看出,程序在编译时就发生了异常。因为在一个方法内使用throw关键字抛出异常对象时,需要使用try…catch语句对抛出的异常进行处理,或者在divide()方法上使用throws关键字声明抛出异常,由该方法的调用者负责处理。但是程序没有这样做。 为了解决上面的问题,对程序进行修改,在divide()方法上,使用throws关键字声明抛出DivideByMinusException异常,并在调用divide()方法时使用try…catch语句对异常进行处理。

完整代码:

Java异常_第13张图片

public class Main {
    public static void main(String[] args) {
        try {
            int res = divide(4, -2);
            System.out.println(res);
        } catch (DivideByMinusException e) {
            System.out.println(e.getMessage());
        }//try...catch捕获并处理异常

    }


    static int divide(int x, int y) throws DivideByMinusException {//方法这里不要忘了用throws关键字声明要抛出异常
        if (y < 0) {
            throw new DivideByMinusException("除数是负数");
        }
        int res = x / y;
        return res;
    }
}

class DivideByMinusException extends Exception {//自定义异常子类继承Exception类

    public DivideByMinusException() {
        super();            // 调用Exception无参的构造方法
    }

    public DivideByMinusException(String message) {
        super(message);    // 调用Exception有参的构造方法
    }
}

上述代码中的main()方法中,第3~8行代码使用try…catch语句捕获处理divide()方法抛出的异常。在调用divide()方法时,如果传入的除数不能为负数,程序会抛出一个自定义的DivideByMinusException异常,该异常最终被catch代码块捕获处理,并打印出异常信息。

你可能感兴趣的:(Java基础学习,java)