1、抛出异常之后
1).使用new在对象上创建异常对象
2).终止当前的执行路径
3).从当前环境中弹出对异常对象的引用
4).异常处理机制接管程序,并开始执行异常处理机制
2、异常处理理论上有两种基本模型
1).终止模型:一旦异常抛出,就表明错误无法挽回,也能回来继续执行。比较实用。
2).恢复模型:异常处理之后继续执行程序。但是可能导致“耦合”。
3、自定异常类(具有带参数的构造器)
class SimpleException extends Exception{ public SimpleException(){} public SimpleException(String msg){ super(msg); } } public class SimpleExceptionDemo{ public void func() throws SimpleException{ System.out.println("Throw SimpleExceptionfrom func()."); throw new SimpleException(); } public void func1() throws SimpleException{ System.out.println("ThrowSimpleException from func1()."); throw new SimpleException("Originated in func1()"); } public static void main(String[] args){ SimpleExceptionDemo sed = new SimpleExceptionDemo(); try { sed.func(); } catch (SimpleException e) { e.printStackTrace(); } try { sed.func1(); } catch (SimpleException e) { e.printStackTrace(); } } }
运行结果:
4、异常说明:实用关键字throws,告知客户端程序员可能会抛出的异常类型。
5、在定义抽象基类和接口时,可以throws一些实际上并不抛出的异常。这样做的好处:为异常先占个位子,以后就可以抛出这种异常而不用修改已有的代码。
6、捕获所有异常(最好放在处理程序列表的末位):
catch (Exception e) { System.err.println("Caught an exception"); }
7、如果当前异常对象重新抛出,那么printStackTrace()方法显示的将是原来异常抛出点的调用栈信息,而非重新抛出点的信息。要想更新这个信息,可以调用fillInStackTrace()方法,这将返回一个Throwable对象,它是通过把当前调用栈信息填入原来那个异常对象而建立的。
8、
public static void main(String[] args) throws Throwable{ try{ throw new Throwable(); }catch(Exception e){ System.err.println("Caught inmain()"); } }因为Throwable是Exception的基类,所以下面程序中将不能再main()里捕获。
9、RuntimeException(或任何从它继承的异常)是一个特例,对于这种异常,编译器不需要异常说明。原因:
1).无法预料的错误。比如在你控制范围之外传递进来的null引用。
2).作为程序员,应该在代码中进行检查的错误。(比如对于ArrayIndexOutOfBoundsException,就得注意一下数组的大小了。)在一个地方发生的异常,常常会在另一个地方导致错误。
10、finally的作用:把除了内存之外的资源恢复到它们的初始状态。例如:已经打开的文件盒网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关。
11、异常丢失:
class FirstException extends Exception{ public String toString(){ return "The firstException."; } } class SecondException extends Exception{ public String toString(){ return "The secondException."; } } public class ErrorFinally{ void firstFunc() throws FirstException{ throw new FirstException(); } void secondFunc() throws SecondException{ throw new SecondException(); } public static void main(String[] args) throws Exception{ ErrorFinally error = new ErrorFinally(); try { error.firstFunc(); } finally{ error.secondFunc(); } } }
运行结果:
可以看到,FirstException不见了,它被finally里的SecondException取代了。
12、异常的限制:当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。这个限制很有用,因为这意味着,当基类使用的代码应用到其派生类对象的时候,一样能够工作(当然,这是面向对象的基本概念),异常也不例外。
1).派生类构造函数的异常说明必须包含基类构造器的异常说明。
2).派生类构造器不能捕获基类构造器抛出的异常。(P275第三段最后一句怎么理解??)
3).派生类的方法可以不抛出异常,即使基类的方法有抛出异常。
4).派生类的方法可以抛出继承自"基类方法所抛出异常"的异常。
请看下面例子:
class BaseException extends Exception{} class FuncException extends Exception{} class OtherfuncException extends FuncException{} class Base { Base() throws BaseException { } void func() throws FuncException { System.out.println("Base.func()"); } void otherFunc() throws FuncException { System.out.println("Base.otherFunc()"); } } public class InheritBase extends Base{ //派生类构造函数的异常说明必须包含基类构造器的异常说明 public InheritBase() throws BaseException { super(); } //派生类的方法可以不抛出异常,即使基类的方法有抛出异常。 void func(){ System.out.println("InheritBase.func"); } //派生类的方法可以抛出继承自"基类方法所抛出异常"的异常,如下OtherfuncException继承自FuncException //因为异常处理程序能捕获FuncException就一定能捕获OtherfuncException。 void otherFunc() throws OtherfuncException{ System.out.println("InheritBase.otherFunc()"); } public static void main(String[] args){ try { Base ib = new InheritBase(); ib.func(); } catch (BaseException e) { System.err.println("Caught BaseException."); } catch (FuncException e) { System.err.println("Caught funcException."); } } }
13、把异常传给控制台
public static void main(String[] args) throws Exception{ }
14、把“被检查的异常”转换为“不检查的异常”:把“被检查的异常”这种功能给屏蔽掉。
1).
try { } catch (BeCheckedException e) { throw new RuntimeException(e); }
这样做的好处:不用“吐下”异常(“吐下”后异常完全消失),也不必把它放到方法的异常说明里(throws),而异常链还能保证你不会丢失任何原始异常的信息。
2).你也可以不写try-catch字句和/或异常说明,直接忽略异常,让它沿着调用栈往上“冒泡”。同时,还可以用getCause()捕获并处理特定的异常,如下例子:
class ZeroException extends Exception{} class FirstException extends Exception{} class secondException extends Exception{} class SomeOtherException extends Exception{} //把”被检查的异常“包装起来 class WrapCheckException{ void throwRuntimeException(int type){ try{ switch(type){ case 0: throw new ZeroException(); case 1: throw new FirstException(); case 2: throw new secondException(); default: return; } }catch(Exception e){ throw new RuntimeException(e); } } } public class TurnOffChecking{ public static void main(String[] args){ WrapCheckException wce = new WrapCheckException(); wce.throwRuntimeException(3); for(int i = 0; i < 4; i++){ try{ if(i < 3) wce.throwRuntimeException(i); else throw new SomeOtherException(); }catch(SomeOtherException e){ System.out.println("SomeOtherException:" + e); }catch(RuntimeException e){ try { //用getCause捕获特定异常 throw e.getCause(); } catch (ZeroException e1) { System.out.println("ZeroException:" + e1); } catch (FirstException e1) { System.out.println("FirstException:" + e1); } catch (secondException e1) { System.out.println("secondException:" + e1); } catch (Throwable e1) { System.out.println("Throwable:" + e1); } } } } }
运行结果:
1).WrapCheckException. throwRuntimeException()把不同的异常包装进了RuntimeException对象。
2).可以不用try块就可以调用throwRuntimeException(),但是,也可以使用try块捕获你想捕获的异常。
3).程序中把getCause()的结果(也就是被包装的那个原始异常)抛出来,然后用它们自己的catch子句进行处理。
以上内容整理自《Java编程思想》,若有遗漏,请您不吝指出。
觉得自己进度有点慢,多么想一口气把这本书看完。我还有几本?17天。现在才267页。我得加速!!