Java 异常的概念

本文最后更新于:2024年3月18日 凌晨

Java 异常的概念

  • 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。
  • 受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发,Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常,异常和继承一样,是面向对象程序设计中经常被滥用的东西,在Effective Java中对异常的使用给出了以下指导原则:
    • 不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常)
    • 对可以恢复的情况使用受检异常,对编程错误使用运行时异常。
    • 避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生)
    • 优先使用标准的异常。
    • 每个方法抛出的异常都要有文档。
    • 保持异常的原子性。
    • 不要在catch中忽略掉捕获到的异常。

[例9-1]:测试异常。

1
2
3
4
5
6
7
public class testException {
public static void main(String[] args) {
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
System.out.println(x+"+"+y+"="+(x+y));
}
}
  • 该程序在编译时无错误,在运行时可能使用不当产生各种问题。

正常运行示例

  • 输入运行命令。
1
java testException 23 45
  • 输出结果: 23+45=68

错误运行现象1:忘记输入命令行参数。

1
java testException
  • 则在控制台将显示数组访问越界的错误信息:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0

错误运行现象2:输入的命令行参数不是整数,例如:

1
java testException 3 3.4
  • 则在控制台将显示数字格式错误的异常信息:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: For input string: "3.4”

  • 可以看出,如果程序运行时出现异常,Java系统通常将自动显示有关异常的信息,指明异常种类和出错的位置。

  • 显然,这样的错误信息交给软件的使用者是不合适的,用户无疑会抱怨你的软件怎么老出错,一个好的程序应能够将错误消化在程序的代码中,也就是在程序中处理各种错误,假如异常未在程序中消化,Java虚拟机将最终接收到这个异常,它将在控制台显示异常信息,为了能防止第一种错误现象,有两个方法。

处理方法1:用传统的防错处理方法检测命令行参数是否达到两个,未达到给出提示。

1
2
3
4
5
6
7
8
9
10
11
public class testException2{
public static void main(String[] args) {
if (args.length<2){
System.out.println("usage:java testException int int");
}else{
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
System.out.println(x+"+"+y+"="+(x+y));
}
}
}
  • 运行时,当命令行参数少于2个时,则输出"usage:java testException int int"

处理方法2利用异常机制,一下为具体代码。

1
2
3
4
5
6
7
8
9
10
11
public class testException3{
public static void main(String[] args) {
try{
int x = Integer.parseInt(args[0]);
int y = Integer.parseInt(args[1]);
System.out.println(x+"+"+y+"="+(x+y));
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("usage:java testException int int");
}
}
}
  • 异常处理的特点是对可能出现异常的程序段用try进行尝试,如果出现异常,则相应的catch语句将捕获该异常,对该异常进行消化处理。

异常的类层次

Java的异常类是处理运行时错误的特殊类,每一种异常类对应一种特定的运行错误,所有的Java异常类都是系统类库中的Exception类的子类,其继承结构如下图所示:

  • Throwable类为该处理层次中的最高层,其中定义了一个异常描述串,以及可获取该描述的getMessage()方法。
    • Error类是一般是指java虚拟机相关的问题,如系统崩溃,虚拟机出错误,动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常应用程序无法处理这些错误,因此应用程序不应该捕获Error对象,也无须在其throws子句中声明该方法抛出任何Error或其子类。
    • Exception可以分为运行时异常(UncheckedExceptions)和非运行时异常(CheckedExceptions)
      • 运行时异常都是RuntimeException类及其子类异常,如NullPointerException,IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理,这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
      • 除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常,这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

系统定义的异常

Exception类有若干的子类,每一个子类代表一种特定的运行时错误,这些子类有的是系统事先定义好并包含在Java类库中的,称为系统定义的运行异常,如下表所示:

系统定义的异常 异常的解释
ClassNotFoundException 未找到要装载的类
ArrayIndexOutBoundsException 数组访问越界
FileNotFoundException 文件找不到
IOException 输入,输出错误
NullPointerException 空指针访问
ArithmeticException 算术运算错误,如除数为0
NumberFormatException 数字格式错误
InterruptedException 中断异常,线程在进行暂停处理时(如睡眠)被调度打断将引发该异常

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!