Java 异常类型

Java教程 - Java异常类型


下图显示了Java异常类型层次结构:

Throwable
 |
 |
 +---Exception. 
 |    |
 |    |
 |    +--- RuntimeException
 |
 +---Error

异常及其子类用于用户程序应捕获的异常条件。您可以子类化Exception以创建自己的自定义异常类型。

错误定义在正常情况下不期望捕获的异常。 Java运行时系统使用错误以指示运行时环境中的错误。 堆栈溢出是这种错误的一个例子。


未捕获异常

这个小程序包括一个有意造成除以零误差的表达式:

public class Main {
  public static void main(String args[]) {
    int d = 0;
    int a = 42 / d;
  }
}

以下是执行此示例时生成的异常:

例子

这里是另一个版本的前面的程序,引入相同的错误,但在一个方法与main()分开:

public class Main {
  static void subroutine() {
    int d = 0;
    int a = 10 / d;
  }

  public static void main(String args[]) {
    subroutine();
  }
}

从默认异常处理程序生成的堆栈跟踪显示如何显示整个调用堆栈:

例2

您可以在println()语句中显示异常描述消息。

例如,catch块可以这样写:

import java.util.Random;

public class Main {
  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 {
        b = r.nextInt();
        c = r.nextInt();
        a = 12345 / (b / c);
      } catch (ArithmeticException e) {
        System.out.println("Exception: " + e); 
        a = 0; // set a to zero and continue
      }
      System.out.println("a: " + a);
    }
  }
}

上面的代码生成以下结果。

什么是Java的内置异常

子类化RuntimeException的异常不需要包含在任何方法的throws列表中。这些被称为未检查异常。

java.lang中定义的未检查异常在下表中列出。

异常 含义
ArithmeticException 算术错误,如除以零。
ArrayIndexOutOfBoundsException 数组索引超出边界。
ArrayStoreException 分配给不兼容类型的数组元素。
ClassCastException 投射无效。
EnumConstantNotPresentException 尝试使用未定义的枚举值。
IllegalArgumentException 用于调用方法的非法参数。
IllegalMonitorStateException 非法监视器操作,例如等待解锁的线程。
IllegalStateException 环境或应用程序状态不正确。
IllegalThreadStateException 请求的操作与当前线程状态不兼容。
IndexOutOfBoundsException 一些类型的索引是超出界限的。
NegativeArraySizeException 使用负尺寸创建的数组。
NullPointerException 无效引用的使用无效。
NumberFormatException 字符串到数字格式的转换无效。
SecurityException 试图违反安全。
StringIndexOutOfBounds 尝试在字符串的边界之外建立索引。
TypeNotPresentException 未找到类型。
UnsupportedOperationException 遇到不支持的操作。

检查的异常在下表中列出。

异常 含义
ClassNotFoundException 找不到类。
CloneNotSupportedException 尝试克隆不实现Cloneable接口的对象。
IllegalAccessException 对类的访问被拒绝。
InstantiationException 尝试创建抽象类或接口的对象。
InterruptedException 一个线程已被另一个线程中断。
NoSuchFieldException 请求的字段不存在。
NoSuchMethodException 请求的方法不存在。

Java自定义异常类

您可以通过定义 Exception 的子类来创建自己的异常类。

异常类没有定义自己的任何方法。它继承由 Throwable 提供的方法。

以下程序创建自定义异常类型。

class MyException extends Exception {
  private int detail;

  MyException(int a) {
    detail = a;
  }

  public String toString() {
    return "MyException[" + detail + "]";
  }
}

public class Main {
  static void compute(int a) throws MyException {
    System.out.println("Called compute(" + a + ")");
    if (a > 10)
      throw new MyException(a);
    System.out.println("Normal exit");
  }

  public static void main(String args[]) {
    try {
      compute(1);
      compute(20);
    } catch (MyException e) {
      System.out.println("Caught " + e);
    }
  }
}

上面的代码生成以下结果。

Java链接异常

链接异常允许您将另一个异常与异常相关联。第二个异常描述了第一个异常的原因。

为了允许链接异常,两个构造函数和两个方法被添加到 Throwable

Throwable(Throwable causeExc) 
Throwable(String msg, Throwable causeExc)

这里是一个例子,说明处理链接异常的机制:

public class Main {
  static void demoproc() {
    NullPointerException e = new NullPointerException("top layer");
    e.initCause(new ArithmeticException("cause"));
    throw e;
  }

  public static void main(String args[]) {
    try {
      demoproc();
    } catch (NullPointerException e) {
      System.out.println("Caught: " + e);
      System.out.println("Original cause: " + e.getCause());
    }
  }
}

上面的代码生成以下结果。