Java的异常
在计算机程序运行的过程中,总是会出现各种各样的错误。
有一些错误时用户造成的,比如,希望用户输入一个int类型的年龄,但是用户输入的是abc:
程序想要读写某个文件的内容,但用户已经把它删除了:
还有一些错误时随机出现的,并且永远不可能避免的。比如:
·网络突然断了,连接不到远程服务器;
·内存耗尽了,程序崩溃了;
·用户点‘打印’,但根本没有打印机;
·……
所以,一个健壮的程序必须处理各种各样的错误。
所谓错误,就是程序员调用某个函数的时候,如果失败了,就表示出错了。
调用方如何获知调用失败的信息?有两种方法:
方法一:约定返回错误码
例如,处理了一个文件,如果返回0,表示成功,返回其它整数,表示约定的错误码:
因为使用int类型的错误码,想要处理就非常麻烦。这种方式常见于底层的C函数。
方法二:在语言层面上提供一个异常处理机制
Java内置了一套异常处理机制,总是使用异常来表示错误。
异常是一种class,因此它本身带有类型信息。异常可以在任何地方抛出,但只需要在上层铺获,这样就和方法调用分离了:
因为Java的异常是class,它的继承管理如下:
从继承关系可知:Throwable是异常体系的根,它继承自Object。Throwable有两个体系:Error和Exception,Error表示严重的错误,程序对此一般无能为力,例如:
• OutOfMemoryError:内存耗尽
• NoClassDefFoundError:无法加载某个Class
• StackOverflowError:栈溢出
而Exception则是运行时的错误,它可以被捕获并处理。
某些异常是应用程序逻辑处理的一部分,应该捕获并处理。例如:
• NumberFormatException:数值类型的格式错误
• FileNotFoundException:未找到文件
• SocketException:读取网络失败
还有一些异常是程序逻辑编写不对造成的,应该修复程序本身。例如:
• NullPointerException:对某个null的对象调用方法或字段
• IndexOutOfBoundsException:数组索引越界
Exception又分为两大类:
- RuntimeException以及它的子类;
- 非RuntimeException(包括IOException、ReflectiveOperationException等等)
Java规定:
• 必须捕获的异常,包括Exception及其子类,但不包括RuntimeException及其子类,这种类型的异常称为Checked Exception。
• 不需要捕获的异常,包括Error及其子类,RuntimeException及其子类。
注意:编译器对RuntimeException及其子类不做强制捕获要求,不是指应用程序本身不应该捕获并处理RuntimeException。是否需要捕获,具体问题具体分析。