Skip to content
异常是表示Java程序运行阶段可能发生的错误的对象。

异常让程序 能够识别错误并做出响应,异常甚至可以帮助程序校正状态,并在可能的情况下继续运行。

Java定义了很多用于处理异常的特性,包括:

如何在代码中处理异常,并妥善地从潜在的问题中恢复;

如何告诉类的用户,预期有潜在的异常;

检测到异常时,如何引发它;

如何使用异常来限制代码,使之更健壮。

在大多数编程语言中,要处理错误条件,都必须完成比处理正常运行的程序更多的工作。可能需要使用复杂的语句结构来处理可能发生的错误。常规的错误处理方式将无法让编译器采用一致的方式进行如下检查:

调用方法时是否使用了正确的参数;

是否将变量设置成了正确的对象;

异常包括可能对程序造成致命打击的错误,还包含其他一些异常情况。通过管理异常,能够管理错误,并妥善地对其进行处理。

通过结合使用特殊的语言特性、编译阶段的一致性检查和一组可扩展的异常类,可在Java程序中更轻松地管理错误和其他异常情况。

有了这些特性,您可以将一个全新的要素加入到类、类层次和整个系统的行为和设计中。类和接口的定义描述了程序在理想情况下的行为。通过将异常处理加入到程序设计中,您可以描述程序在不理想的情况下的行为,让使用这些类的人知道,在这些情况下结果将如何。

**异常类**
发生异常时,应用程序可能退出,并且屏幕上会显示一组难以理解的错误。这些错误就是异常。异常可能是由Java虚拟机(JVM)和您使用的类引发的,也可能是程序故意引发的。

除引发异常外,还可捕获异常。捕获异常指的是对异常情况进行处理,以避免程序崩溃。

在Java中,异常是对象,即它们是从类Throwable派生而来的类的实例。当异常被引发时,将创建Throwable类的一个实例。

Throwable有两个子类:Error和Exception。Error实例是JVM实例内部的错误,这种错误很少见,但通常是致命的,对于它们,您无能为力(要么捕获它们,要么引发它们)。

Exception类与编程的关系更为紧密。Exception的子类分两组。

unchecked异常(RuntimeException类的子类),如ArrayIndexOutofBounds、SecurityException和NullPointException。

checked异常,如EOFException和MalformedURLException。

unChecked异常也叫运行阶段异常,通常是由于代码不够健壮造成的。如果进行了正确的检查,以确保代码不超越数组边界,将不会发生ArrayIndexOutofBounds异常。除非使用一个之前未被声明为用来存储对象的变量,否则不会发生NullPointerException异常。

警告:如果程序导致unchecked异常,应通过改善代码来消除问题。对于可在创建Java程序时消除的编程错误,不要依赖于异常管理来处理。

checked异常表明发生了奇怪且无法控制的事情。例如,如果读取文件内容时意外地跨越了文件尾,将发生EOFExceptions异常;当Web地址(也叫URL)的格式不正确时,将发生MaleformedURLException异常。这组异常包含一些您创建的异常,用于指出程序中发生了不正常的情况。

与其他类一样,异常也被组织成层次结构,其中超类表示较通用的错误,子类表示更具体的错误。当您在代码中处理异常时,这种组织结构将更为重要。
主要的异常类(Throwable、Exception和RuntimeException)都位于java.lang包中。在Java类库中,还有很多其他的包定义了其他异常,这些异常用于整个类库中。

java.io包定义了一个名为IOExcetion的通用异常类,它是java.io包中的输入和输出异常类(EOFException和FileNotFoundException)、java.net包中的网络异常类(如MalformedURLException)以及java.utile包中异常类(如ZipException)的父类。

**管理异常**
在很多情况下,当您使用了可能引发异常的方法时,Java编译器将要求您对异常进行管理:您必须在代码中对这些异常进行处理,否则程序将不能通过编译。

异常一致性检测
对Java类库使用得越多,遇到类似于下而被种异常的可能性就越大:
Exception java.lang.InterruptedException must be caught or it must be declared in the of this method.
在Java中,方法可以指可能引发的错误类型。例如,读取文件的方法可能引发IOException错误,因此声明这些方法时,需要使用一个特殊的限定符来指出可能的错误。当您在Java程序中使用这些方法时,必须保护代码不受这些异常的影响。

这种规则是由编译器执行的,编译器以相同的方式对代码进行检测,以确保您调用方法时提供的参数数目和类型都是正确的。

进行这种检测降低了程序由于致使错误而崩溃的可能性,因为您将预先知道程序使用的方法可能引发什么样的异常。

如果您定义方法时,指出了它们可能引发的异常,Java将命令该方法的用户必须对这些错误进行处理。

**保护代码和捕获异常**
假设您编写代码,并在编译时遇到异常消息。根据该消息,您必须捕获这种错误或声明方法必须引发它。首先捕获可能的异常,这需要完成两项工作:

将包含可能引发异常的方法的代码放在try块中;

将catch块中对异常进行处理。

try块尝试执行一个代码块,看看能否挪它而导致异常。如果失败并发生异常,将由catch块进行处理。


为了处理异常,将parseFloat()放在try块中,并建立了一个与之相关联的catch块,该catch块将接收try中引发的任何NumberFormatException对象。

catch子句的圆括号中的内容类似于方法定义中的参数列表,其中包含将捕获的异常类和变量名。在catch块中,可以使用该变量名来引用异常对象。

异常对象包含方法getMessage(),它显示详情的错误消息,描述发生的情况。
至此,介绍的示例都捕获特定类型的异常。由于异常类被组织成层次结构,同时可以在期望超类的地方使用子类,因此,可以在一条catch语句中捕获一组异常。编写处理来自文件、Internet服务器等的输入/输出的程序时,需要处理多种类型的IOException异常(IO表示输入/输出)。该异常有两个子类:EOFException和FileNotFoundException。通过捕获IOException,也可以捕获其子类的实例。
要捕获多种没有任何继承关系的异常,可以将多个catch块用于同一个try块,如下所示:


使用多个catch块时,将执行第一个匹配的catch块,并忽略其他catch块。

在catch块中使用Exception超类,并在后面的多个catch块中使用Exception的子类时,可能发生意料之外的问题。例如,输入/输出异常EOFException的超类。如果将IOException块放在EOFException块前面,该超类将不会捕获任何异常。

还可在一条catch语句中捕获多种异常。为此,可以使用管理字符分隔异常类,如下所示:


上述代码在同一个catch块中捕获两个异常:EOFException 和FileNotFoundException。将发生的异常赋给了参数exc,再调用了其getMessage()方法。

在列表中与引发的异常匹配的第一个类将被赋给参数。在catch语句中,指定多个存在继承关系的异常类时,必须按正确的顺序排列它们,下面的代码就不可行:

其中的一种修复错误的方式是,将超类放在catch语句的末尾。


catch语句必须与try块配套。在catch语句中指定的异常必须是相应的try可能引发的异常(或其超类),否则编译器将显示错误消息。

本站总访问 — 次