当异常抛出后,会有几件事情发生,同java中其他对象的创建一样,将用new在堆中创建异常对象。然后当前执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时异常处理机制接管程序,寻找一个恰当的地方继续执行程序。
异常处理理论上有两种模型,终止模型和恢复模型,恢复模型虽然很吸引人但很不实用。尝试把try块放在while里面,直到得到满意的答案。
所有标准异常类都有两个构造器,一个是默认空的构造器,另一个是接受字符串作为参数,以便把相关信息放入异常对象构造器。
throw new NullPointerException("");
如果在方法内部抛出异常(或者在方法内部调用其他方法抛出异常),这个方法将在抛出的过程中结束。
public void method(param) throws xxxException{
........
}
要是不希望方法就此结束,可以在方法内设置一个特殊的块来捕获异常。try{} cathc{}处理。
public void method(param) throws xxxException{
try{
........
}catch( xxxException e1){
log.error("xx", e1);
..................
throw new xxException("xxxx!");
}catch( xxxException e2){
log.error("xx", e2);
......................
throw new xxException("xxxx!");
}finally{
.......................finally总是将被执行。
}
}
注意,catch()吞食异常后应该处理,否则异常将丢失。
try{
}catch(xxException e){
}
即使发生了异常,但catch捕获没做处理,运行时不会抛错,和正常运行一样,没有任何信息输出。
当异常被抛出时,异常处理机制将负责搜寻参数与异常类型相匹配的第一个处理程序,然后进入catch子句执行。注意只有匹配catch子句才能得到执行。如果许多不同的方法返回的相同类型的异常,只需要一个针对此异常的处理程序。
通过捕获异常类型的基类Exception可经捕获所有的类型的异常,但它不会含太多具体的信息。
RuntimeException和非RuntimeException的区别
假设自己定义了个MyException
public String getFirstTwo(String src){
//if(src == null) throw new MyException( "String is null ");
return src.substring(0, 2);
}
注释的语句不放开,不会出错
如果别的地方调用了getFirstTwo(null),在getFirstTwo方法中,null.substring(0,2)方法是会抛出运行时异常NullPointerException的,虽然getFirstTwo方法并没有申明会throws NullPointerException,但是实际运行中这个异常还是会从getFirstTwo方法抛出给调用这个方法的地方。而如果把注释语句放开,则无法通过编译,MyException是一个非运行时异常,如果方法中的语句可能抛出这个异常必须将方法声明为public String getFirstTwo(String src) throws MyException才可以
有时希望把异常重新抛出,尤其是在使用Exception捕获所有异常时,既然已经得到了当前异常对象的引用,可以把它重新抛出。
重新抛出异常会把异常给上一级环境的异常处理程序,同一个try块的后续catch子句将被忽略,异常对象所有信息得以保持,上一级环境可以得到所有信息。
//: exceptions/Rethrowing.java
// Demonstrating fillInStackTrace()
public class Rethrowing {
public static void f() throws Exception {
System.out.println("originating the exception in f()");
throw new Exception("thrown from f()");
}
public static void g() throws Exception {
try {
f();
} catch(Exception e) {
System.out.println("Inside g(),e.printStackTrace()");
e.printStackTrace(System.out);
throw e;
}
}
public static void h() throws Exception {
try {
f();
} catch(Exception e) {
System.out.println("Inside h(),e.printStackTrace()");
e.printStackTrace(System.out);
throw (Exception)e.fillInStackTrace();
}
}
public static void main(String[] args) {
try {
g();
} catch(Exception e) {
System.out.println("main: printStackTrace()");
e.printStackTrace(System.out);
}
try {
h();
} catch(Exception e) {
System.out.println("main: printStackTrace()");
e.printStackTrace(System.out);
}
}
} /* Output:
originating the exception in f()
Inside g(),e.printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.f(Rethrowing.java:7)
at Rethrowing.g(Rethrowing.java:11)
at Rethrowing.main(Rethrowing.java:29)
main: printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.f(Rethrowing.java:7)
at Rethrowing.g(Rethrowing.java:11)
at Rethrowing.main(Rethrowing.java:29)
originating the exception in f()
Inside h(),e.printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.f(Rethrowing.java:7)
at Rethrowing.h(Rethrowing.java:20)
at Rethrowing.main(Rethrowing.java:35)
main: printStackTrace()
java.lang.Exception: thrown from f()
at Rethrowing.h(Rethrowing.java:24)
at Rethrowing.main(Rethrowing.java:35)
*///:~