(三十)异常
在程序运行中(非编译),任何中断正常流程的因素都被认为是异常。按照面向对象思想,Java语言用Java类来描述异常。所有异常类的祖先类为java.lang.Throwable类,它的实例表示具体的异常对象,可以通过throw语句抛出。Throwable类提供了访问异常信息的一些方法,常用的方法包括:
(1)getMessage() 返回String类型的异常信息。
(2)printStackTrace() 打印跟踪方法调用栈而获得的详细异常信息。在程序调试阶段,此方法可用于跟踪错误。
Throwable类有两个直接子类:
(1)Error类——表示紧靠程序本身无法恢复的严重错误,属于JVM层次的严重错误,比如内存空间不足,或者Java虚拟机的方法调用栈溢出。在大多数情况下,遇到这样的错误时,建议让程序终止。此外,编译器不会检查Error是否被处理,因此在程序中不推荐去捕捉Error类型的异常,主要原因是运行时异常多是由于逻辑判断错误导致的,属于应该解决的错误,也就是说,一个正确的程序是不应该存在Error的。OutOfMemoryError、ThreadDeath等都属于错误。当这些异常发生时,JVM一般会选择将线程终止。
(2)Exception类——表示程序本身可以处理的异常。当程序运行时出现这种异常,应该尽可能地处理异常,并且使程序恢复运行,而不应当随意终止程序。分为检查异常(checked exception)和运行时异常(runtime exception)
JDK中预定义了一些具体的异常。常见异常类的类框图如下:
(3)用户可以创建自己的异常类(所有异常都是java.lang.Throwable的子类),并自由选择在何时用throw关键字抛出异常
二、throws、throw用法
异常处理:抛出异常和try-catch捕获异常
①编译异常(受检查异常):比如对其异常处理,否则编译不通过
static void f(int n) throws FileNotFoundException
//throws:方法抛出异常,但是没有能力处理该异常或者需要通过该异常向上汇报处理结果,可以在方法声明时使用throws来抛出异常
{
if (n == 0) {
throw new FileNotFoundException("hello Exception!");
/*
* throw来抛出一个Throwable类型的异常。一旦遇到throw语句,后面的代码都不会被执行。
* 然后便是异常处理---包含该异常的try-catch处理或者向上抛出
*/
} else {
System.out.println("right!");
}
}
static void f1(int n)
{
if (n == 0) {
try {
throw new FileNotFoundException("hello Exception!");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/*
* throw来抛出一个Throwable类型的异常。一旦遇到throw语句,后面的代码都不会被执行。
* 然后便是异常处理---包含该异常的try-catch处理
*/
} else {
System.out.println("right!");
}
}
②运行时异常:
throw new ArrayIndexOutOfBoundsException("数组下标越界");
出现运行时异常后,系统会把异常一直往上层抛出,直到遇到处理代码为止。若没有处理块,则抛到上层;如果是多线程就用Thread.run()方法抛出,如果是单线程,就用main()方法抛出。抛出后,若是线程,则线程退出;若是主程序抛出异常,那么整个程序退出。所以,若不对运行时异常进行处理,后果很严重。一旦发生,要么线程中止,要么是主程序终止。
//单线程
static void f1()
{
throw new ArrayIndexOutOfBoundsException("数组下标越界");
}
static void f2()
{
f1();
}
public static void main(String[] args) throws FileNotFoundException
{
f2();
}
等复习到线程再补线程异常
三、Exception异常:运行时异常(不受检查异常)和编译异常(受检查异常)
①运行时异常(不受检异常):RuntimeException类极其子类表示JVM在运行期间可能出现的错误。比如说试图使用空值对象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。
②编译异常(受检异常):Exception中除RuntimeException极其子类之外的异常。如果程序中出现此类异常,比如说IOException,必须对该异常进行处理,否则编译不通过。在程序中,通常不会自定义该类异常,而是直接使用系统提供的异常类。