好异常处理提供了处理程序错误的统一机制。事实上,Java 语言通过向调用者提出异
常警告的方式而显著地提升了软件开发中的异常处理能力。这种方式把 Java
“
语言中的 方
法(method)”进行了扩展和增强,使之包括了自身的错误条件。下面就让我们看一个例子,
这个例子说明了这种情况。
以下是 FileInputStream 构造器之一的原型:
public
FileInputStream(String name)
throws
FileNotFoundException Java
“
”
的方法和构造器必须声明他们在被调用时可能 扔出 的异常,采用的关键字就是
“
throws
”。这种在方法原型中出现的异常提示增加了编程的可靠性。
显而易见,这种方式是向方法的调用者提示了可能出现的异常条件,这样调用者就
可以对这些异常作出适当的相应处理。以下代码示意我们是如何捕获并且处理
FileNotFoundException 这一异常的:
1234567891011
try
{
FileInputStream fis =
new
FileInputStream(args[
0
]);
// other code here ...
}
catch
(FileNotFoundException fnfe)
{
System.out.println("File: " + args[
0
] + " not found. Aborting.");
System.exit(
1
);
}
Java 异常处理还有其他一些优秀的特性,这就是可检查异常、用户定义异常和在 JDK
1.4
中推出的新型 Java 记录 API(Java Logging API)。java.lang.Exception 的所有子类都属于可
检查异常。可检查异常(checked exception)是扔出该异常的方法所必须提示的异常,这种异
常必须被捕获或者向调用者提示。用户定义异常(User-defined exceptions)是定制的异常类,
这种异常类扩展了 java.lang.Exception 类。优良的 Java 程序规定定制异常封装、报告和处理
他们自己独有的情况。最新的 Java 记录 API(logging API)则可以集中记录异常。
不好的 Java 异常处理
不好的一面包括两种情况:滥用不可检查异常(unchecked exceptions)和滥用 catchall
构造器等。这两种方式都使得问题变得复杂起来。
有一种类别的异常属于 RuntimeException 的子类,这种异常不会受到编译器的检查。
比如,NullPointerException
和 ArrayStoreException 就是这种类型异常的实例。程序员可以
对 RuntimeException 进行子类化以回避检查异常的限制,从而便于产生这些异常的方法
为其调用者所使用。
专业的开发团队应当只允许在很少的情况下才可以这样做。
第二种异常处理的陋习是 catchall
“
构造器。所谓的 catchall
”
构造器 就是一种异常捕获
代码模块,它可以处理所有扔给它的可能异常。
以下是 catchall 处理器的实例:
123456789
try
{