前言
在一个方法的运行过程中,如果发生了异常,则这个方法(或者是Java虚拟机)生成一个代表该异常的对象(它包含了异常的详细信息),并把它交给运行时系统,运行时系统寻找相应的代码来处理这一异常。我们把生成异常对象并把它提交给运行时系统的过程称为抛出(throw)异常。
当Java运行时系统得到一个异常对象时,它将会沿着方法的调用栈逐层回溯,寻找处理这一异常的代码。找到能够处理这类异常的方法后,运行时系统把当前异常对象交给这个方法进行处理,这一过程称为捕获(catch)异常。
错误和异常
Throwable类是 Java 语言中所有错误或异常的超类。
Throwable有两个子类:Error和Exception
Exception(异常):是应用程序中可能的可预测、可恢复问题。一般大多数异常表示中度到轻度的问题。异常一般是在特定环境下产生的,通常出现在代码的特定方法和操作中。在 EchoInput 类中,当试图调用 readLine方法时,可能出现 IOException 异常。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
Error(错误):表示运行应用程序中较严重问题,不可恢复。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。
可控制异常和不可控制异常的划分
Java中的异常分为两大类:
Checked Exception(非Runtime Exception)
Java认为Checked异常都是可以被处理的异常,所以Java程序必须显式的处理Checked异常,如果程序没有处理checked异常,程序在编译时候将发生错误。
我们比较熟悉的Checked异常有:- java.lang.ClassNotFoundException
- java.lang.NoSuchMetodException
- java.io.IOException
Unchecked Exception(Runtime Exception)
Runtime Exception如除数是0、数组下标越界等,其产生频繁,处理麻烦,若显示申明或者捕获将会对程序的可读性和运行效率影响很大。所以由系统自动检测并将它们交给缺省的异常处理程序。当然如果你有处理要求也可以显示捕获它们。
我们比较熟悉的RumtimeException类的子类有:- java.lang.ArithmeticException
- java.lang.ArrayStoreExcetpion
- java.lang.ClassCastException
- java.lang.IndexOutOfBoundsException
- java.lang.NullPointerException
java.lang.Error:Throwable的子类,用于标记严重错误。合理的应用程序不应该去try/catch这种错误。绝大多数的错误都是非正常的,就根本不该出现的。
java.lang.Exception:Throwable的子类,用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。
Error和RuntimeException 及其子类都是不可控制的异常(unchecked exceptions),而所有其他的Exception类都是可控制的异常(checked exceptions)。
Checked Exceptions:通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。比如FileNotFoundException, ParseException等。可控制的异常发生在编译阶段,必须要使用try…catch(或者throws)进行处理,否则编译不通过。
Unchecked Exceptions:通常是如果一切正常的话本不该发生的异常,但是的确发生了。发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的。比如ArrayIndexOutOfBoundException, ClassCastException等。从语言本身的角度讲,程序不该去catch这类异常。虽然能够从诸如RuntimeException这样的异常中catch并恢复,但是并不鼓励终端程序员这么做。 因为这类错误本身就是bug,应该被修复,出现此类错误时程序就应该立即停止执行。 因此,面对Errors和Unchecked Exceptions应该让程序自动终止执行,程序员不该做诸如try/catch这样的事情,而是应该查明原因,修改代码逻辑。
处理方法
Java中凡是继承自Exception,而不继承自RuntimeException类的异 常都是非运行时异常。
对于非运行时异常(Checked Exception),必须要对其进行处理,否则无法通过编译。
处理方式有两种:
- 使用try..catch..finally进行捕获;
- 在产生异常的方法声明后面写上throws 某一个Exception类型,如throws Exception,将异常抛出到外面一层去。
对于运行时异常(Runtime exception),可以对其进行处理,也可以不处理。推荐不对运行时异常进行处理。
- 一般而言,Checked Exception 表示这个Exception 必须要被处理,也就是说程序设计者应该已经知道可能会收到某个Exception(因为要try catch住) ,所以程序设计者应该能针对这些不同的Checked Exception 做出不同的处理。
- 而Runtime Exception 通常会暗示着程序上的错误,这种错误会导致程序设计者无法处理,而造成程序无法继续执行下去。