Java异常

Throwable类

Throwable类是整个异常体系类的父级类,它实现了Serializable接口,它的父类是Object类,它的子类有Exception和Error,这2个子类下面都有很多子类。

  • Error是程序发生了重大错误,不能解决,只能避免,比如:内存泄漏

  • Exception:可对其进行处理的异常

Java异常_第1张图片
20160907101613.jpg

受检异常和非受检异常

  • 受检异常(checkedException):程序必须处理该异常。除了RuntimeExcetion及其子类(运行时异常),其他的Exception及其子类都属于受检异常,这种异常的特点是java编译器会检查它,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

  • 非受检异常(uncheckedException):编译器不要求强制处置的异常。包括运行时异常(RuntimeException与其子类)和错误(Error)。

Java异常_第2张图片
QQ截图20180417153847.png

运行时与非运行时异常

Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。

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

运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,不过一般情况下不自定义检查异常。

异常处理

程序运行过程中可能会出现异常情况,比如被0除、对负数计算平方根等,还有可能会出现致命的错误,比如内存不足,磁盘损坏无法读取文件等,对于异常和错误情况的处理,统称为异常处理。

Java异常处理主要通过5个关键字控制:try、catch、throw、throws和finally。try的意思是试试它所包含的代码段中是否会发生异常;而catch当有异常时抓住它,并进行相应的处理,使程序不受异常的影响而继续执行下去;throw是在程序中明确引发异常;throws的作用是如果一个方法可以引发异常,而它本身并不对该异常处理,那么它必须将这个异常抛给调用它的方法;finally是无论发不发生异常都要被执行的代码。

关键字:throw,throws,try和catch的用法如下:

  1. throws出现在方法的声明中,表示该方法可能会抛出的异常,允许throws后面跟着多个异常类型

  2. throw出现在方法体中,用于抛出异常。当方法在执行过程中遇到异常情况时,将异常信息封装为异常对象,然后throw。

  3. try出现在方法体中,它自身是一个代码块,表示尝试执行代码块的语句。如果在执行过程中有某条语句抛出异常,那么代码块后面的语句将不被执行。一个try后面可以跟多个catch,但不管多少个,最多只会有一个catch块被执行。

  4. catch出现在try代码块的后面,自身也是一个代码块,用于捕获异常try代码块中可能抛出的异常。catch关键字后面紧接着它能捕获的异常类型,所有异常类型的子类异常也能被捕获。

常见的异常:

  • NullPointerException 空指针异常

  • ArrayIndexOutOfBoundsException 数组下标越界异常

  • StringIndexOutOfBoundsException 字符串下标越界异常

  • ClassCastException 类型转换异常

  • NumberFormatException 数字转换异常


代码示例

下面来看看代码,从代码中深刻理解Exception

例1:

  Scanner scanner = new Scanner(System.in);
  // 下面可以引发InputMismatchException,为非受检异常
  int i = scanner.nextInt();//这里定义为int,如果键盘输入为string类型则会出现异常
  System.out.println(i);

  // 下面这个是受检异常,必须处理,否则编译不通过
  try {
    Thread.sleep(1000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }

例2:

  int i;
  Scanner scanner = new Scanner(System.in);
  try {// 放可能发生异常的代码块
    i = scanner.nextInt();
  } catch (InputMismatchException e) {
    System.out.println("捕获到了InputMismatchException");
  } catch (Exception e) {// 捕获异常,对异常的处理
    System.out.println("发生了异常");
    e.printStackTrace();
  } finally {// 始终要执行的代码
    System.out.println("无论有没有发生异常我是一定会执行的");
  }
  System.out.println("----程序结束");

将上面的代码运行2次输出结果分别是:

第一次输入123结果

123

无论有没有发生异常我是一定会执行的

----程序结束

第二次输入asdf结果

asdf

捕获到了InputMismatchException

无论有没有发生异常我是一定会执行的

----程序结束

由这2次结果可以看出,finally不能是否发生异常都执行了;try后面可以跟着多个catch,但是最多只能执行一个catch。可以在try后面加任意数量的catch块,如果try中的代码发生异常,异常被抛给第一个catch快,如果抛出异常的数据类型与第一个catch类型匹配,它就在这里被捕获,如果不匹配,它会传入第二个catch块,以此类推知道最后一个catch块。

例3:

  public static void main(String[] args) {
    int a = 10, b = -4;
    int result;
    try {
      result = div(a, b);
      System.out.println("result=" + result);
    } catch (Exception e) {
      System.out.println("捕获到了异常");
      System.out.println(e.getMessage());
    }
    System.out.println("---程序结束");
  }

  // 在方法后面用throws关键字 把异常抛出去,谁调用谁处理
  public static int div(int a, int b) throws Exception {
    if (b < 0) {
    // 使用throw抛出一个异常
      throw new Exception("被除数不能小于0");
    }
    if (b == 0) {
    // 使用throw抛出一个异常
      throw new Exception("被除数不能为0");
    }
    return a / b;
  }

输出为:

捕获到了异常

被除数不能小于0

---程序结束

这个例子是自定义什么条件下抛出异常,我们定义了被除数为0或者被除数小于0时抛出异常,并通过throws把异常抛出,谁调用这个方法,谁就处理这个异常或者继续抛出。


扩展:错误和异常的区别(Error vs Exception)

1)java.lang.Error:Throwable的子类,用于标记严重错误。合理的应用程序不应该去try/catch这种错误。绝大多数的错误都是非正常的,就根本不该出现的。

2)java.lang.Exception: Throwable的子类,用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。

扩展:错误和异常的区别(Error vs Exception)
1)java.lang.Error: Throwable的子类,用于标记严重错误。合理的应用程序不应该去try/catch这种错误。绝大多数的错误都是非正常的,就根本不该出现的。
2)java.lang.Exception: Throwable的子类,用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。


声明自定义异常

在java中可以自定义异常,编写自己自定义的异常时需要注意:

  • 所有异常都必须是Throwable的子类
  • 如果希望写一个受检异常类,则需要继承Exception类
  • 如果希望写一个运行时异常类,那么需要继承RuntimeException类

请尊重作者劳动成果,转载请标明原文链接:https://www.jianshu.com/p/aaf0103604d8

你可能感兴趣的:(Java异常)