(一)异常的概念
(二)异常处理格式
(三)throws关键字(异常说明)与throw 关键字
(四)自定义异常
(五)RuntimeException
(六)与Exception的区别
(七)异常的匹配
(一)异常的概念
-
异常情形:异常情形是阻止当前方法或者作用域继续执行的问题。
-
异常情形与普通错误的区分
-
抛出异常后发生的事情:
(1)首先,同java中其他对象的创建一样,将用new在堆上创建异常对象;
(2)然后,当前执行路径被终止(不能继续执行下去了),并且从当前环境中弹出对异常对象的引用;
(3)此时,异常处理机制管理程序,并且寻找一个恰当的地方来继续执行程序。(这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态下恢复,使程序继续运行或者换一种方式运行。 -
能够抛出任意类型的Throwable对象,它是异常对象的根。
(1)Error:表示编译时和系统错误。Error类描述了Java运行时内部错误和资源耗尽错误。应用程序不抛出此类异常,这种内部错误一旦出现,除了告知用户并使程序安全终止之外,再无能无力。这种情况很少出现。
(2)RuntimeEcpection(运行时异常):由于程序错误导致的异常。
(3)IOException(输入输出异常):由于像I/O错误这类问题导致的异常。
(二)异常处理格式
try{有可能出现异常的语句 ; }
[catch (异常类1 对象) { } ... ]
[catch (异常类2 对象) { } ... ]
......
[finally { 异常的出口 }]
- try 块:捕获异常。出现异常时不希望方法就此结束,在方法内部设置了一个特殊的块来捕获异常。
- catch 块:
- (1)异常处理程序。抛出的异常必须在某处的得到处理,这个地点就是异常处理程序,并且针对每个要捕获的异常,都得准备相应的处理程序。
(2) 异常程序必须紧跟在try 块之后,当异常被抛出后,异常处理机制将负责搜寻参数与异常类型相匹配的第一个处理程序。然后进入catch 子句执行,此时认为异常得到了处理。一旦catch子句结束,则程序处理的查找过程结束。
(3)多个catch 捕获异常,写异常时,由小到大写,从子类到父类,先写子类,再写父类,否则父类直接处理,则子类会出现异常。
(4)可以在catch 块中使用 void printStackTrace()方法打印Throwable 和Throwable的调用栈轨迹。调用栈显示了“把你带到一场抛出地点”的方法调用序列,输出到便准错误。 - finally :
(1)使用finally进行清理。
(2)对于一些代码,可能会希望无论try块中的异常是否抛出,它们都能执行。
(3)当要把内存之外的资源恢复到它们的初始状态时,就要用到finally子句。这种需要清理的资源包块:已经打开的文件或者网络连接,在屏幕上画的图形,或者外部世界的某个开关。
finally一定会执行,除了两种特殊情况:
(1)如果在finally块执行之前调用System.exut()VM停止;
(2)未知错误。
finally块在return 执行之后执行,尽量不在finally块中使用return语句 。
举例:
public class ExceptionTest {
public static void main(String[] args) {
System.out.println("[1].数学计算开始前");
try {
System.out.println("[2].进行数学计算:"+10/0);
}
catch (ArithmeticException e) {
e.printStackTrace();
}
finally {
System.out.println("[Finally]不管是否产生异常,都执行此语句");
}
System.out.println("[3].数学计算结束后"); }
}
(三)throws关键字(异常说明)与throw 关键字
- throws关键字(异常说明):
(1)在进行方法定义的时候,如果要告诉调用者本方法可能产生哪些异常,就可以使用throws方法进行声明。即,如果该方法出现问题后不希望进行处理,就使用throws抛出。
(2)如果现在调用了throws声明的方法,那么在调用时必须明确的使用try…catch…进行捕获,因为该方法有可能产生异常,所以必须按照异常的方式来进行处理。
(3)主方法main()也可以使用throws抛出,抛出后由JVM直接处理。
(4)throws用在方法上。 - throw 关键字:
(1)thorw是直接编写在语句之中,表示人为进行异常的抛出。如果现在异常类对象实例化不希望由JVM产生而由用户产 生,就可以使用throw来完成。
(2)throw用在方法中。
注:throws 与 throw 将在下面举例2中使用。
(四)自定义异常
java体系中不可能预见所有的希望加以报告的错误,因此可以自己定义异常类来表示程序中可能遇到的特定问题。
- 要自己定义异常类,必须从已有的异常类继承。最好选择意思相近的异常类。
- 建立新的异常类型最简单的方法就是让编译器产生默认的构造方法,自己只需要写很少的代码。
举例2:
package www.fanfan.com;
//自定义异常类
class SimpleException extends Exception{ }
public class InheritingException {
public void f() throws SimpleException{
System.out.println("Throw SimpleExpection from f()");
throw new SimpleException();
}
public static void main(String[] args) {
InheritingException inheritingException = new InheritingException();
try{
inheritingException.f();
}
catch (SimpleException e){
System.out.println("Catch it!");
}
}
}
(五)RuntimeException
- RuntimeException:不受检查异常。(运行时异常)
- 属于运行时异常的类型有很多,它们会被java虚拟机自动抛出,因此不必在异常说明中把它们列出来。这些异常都是从RuntimeException继承而来。
- 这种异常属于错误,将会被自动捕获。
- 尽管通常不需要捕获RuntimeException异常,但是可以在代码中抛出RuntimeException类型的异常。
- RuntimeException如果没有被捕获将会直达main(),在程序退出前调用异常的printStackTrace()方法。
- 注意:只能在代码中忽略RuntimeException(及其子类)类型的异常,其他类型的异常都是由编译器强制实施的。因为RuntimeException
代表的是编程错误。
(六)与Exception的区别
- 使用Exception是RuntimeException的父类,使用Exception定义的异常都要求必须使用异常处理,而
使用RuntimeException定义的异常可以由用户选择性的来进行异常处理。 - 常见的RuntimeException:ClassCastException、NullPointerException等。
(七)异常的匹配
抛出异常的时候,异常处理系统会按照代码的书写顺序找出“最近”的处理程序。找到匹配的处理程序之后,就认为异常得到了处理,然后就不再继续查找。
查找的时候并不要求抛出的异常同处理程序所声明的异常完全匹配。派生类的对象也可以匹配其基类的处理程序。
举例3:
class Annoyance extends Exception{}
class Sneeze extends Annoyance{}
public class Human {
public static void main(String[] args) {
try{
throw new Sneeze();
}
catch (Sneeze s){
System.out.println("Catch Sneeze");
}
catch (Annoyance a){
System.out.println("Catch Annoyance");
}
System.out.println("-------------------");
try {
throw new Sneeze();
}
catch (Annoyance a){
System.out.println("Catch Annoyance");
}
}
}