(第9章笔记)
//捕获错误最理想的是在编译期间,然而有些问题必须在运行期间解决 //异常,if—else or 断言 ? //异常:程序执行时的一些非正常的情况,如果有不正确的数据、逻辑等会抛出异常。是程序员写给其他程序员的,比方说我写了 //一个方法,如果其他人使用我这个方法的时候有可能不按我想的路子使用,可能会引起我的方法产生不正常的处理,这时候我要 //使用异常,而且可以决定产生异常了是由我这个方法本身进行处理(catch语句中处理)还是交给调用者进行处理(直接把异常抛出) //if—else:就是我写的方法,要进行逻辑判断 //断言:是我在调用别人写的方法,或者我处理程序时对通过其他途径得到的数据(如调用别人方法的返回值(好象不建议用断言), //通过参数传入的值)等进行假设它就是某值时使用的。是方便开发、调试提供的一个语法元素 //Throwable直接从Object继承,Throwable派生出Exception和Error package com; public class Test8 { public static void f() throws Exception { //throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。 //多个异常可以使用逗号隔开,方法调用者在使用时做好准备接受异常 System.out.println("Originating the exception in test()"); throw new Exception("thrown from f()"); } public static void g() throws Throwable{ try{ f(); }catch(Exception e){ System.out.println("Inside g(), e.printStackTrace()"); e.printStackTrace(); // throw e; throw e.fillInStackTrace(); //不同于e,e.fillInStackTrace()将此处设为新的违例起点 } } public static void main(String[] args) throws Throwable { // TODO Auto-generated method stub String string = ""; if(string == null) throw new NullPointerException(); /*对于throw,首先执行new 表达式,创建一个不在 程序常规执行范围 之内的对象。而且理所当然,会为那个对象调用构建器。随后,对象实际会从方法中返回,尽管对象的类型通常并不是 方法设计为返回的类型。为深入理解违例控制,可将其想象成另一种返回机制——但是不要在这个问题上深究,否则会遇 到麻烦。通过掷出一个违例,亦可从原来的作用域中退出。但是会先返回一个值,再退出方法或作用域*/ else System.out.println("string is not null"); try{ g(); }catch(Exception e){ System.out.println("Caught in main, e.printStackTrace()"); e.printStackTrace(); } } }
运行结果:
string is not null
Originating the exception in test()
Inside g(), e.printStackTrace()
Caught in main, e.printStackTrace()
java.lang.Exception: thrown from f()
at com.Test8.f(Test8.java:19)
at com.Test8.g(Test8.java:23)
at com.Test8.main(Test8.java:42)
java.lang.Exception: thrown from f()
at com.Test8.g(Test8.java:28)
at com.Test8.main(Test8.java:42)
package com; class BaseballException extends Exception {} class Foul extends BaseballException {} class Strike extends BaseballException {} abstract class Inning { Inning() throws BaseballException {} void event() throws BaseballException { //声明抛出异常,但实际上可以置之不理 } abstract void atBat() throws Strike, Foul; void walk() {} } class StormException extends Exception {} class RainedOut extends StormException {} class PopFoul extends Foul {} interface Storm { void event() throws RainedOut; void rainHard() throws RainedOut; } public class Test8_2 extends Inning implements Storm { Test8_2() throws RainedOut, BaseballException {} //因为基础构建器抛出BaseballException,所以此处必须抛出BaseballException Test8_2(String s) throws Foul, BaseballException {} //方法必须与基础类保持一致,下面会出现一个变异错误 // void walk() throws Foul {} //接口禁止将异常加到基类中已存在的方法里,但如果方法不在基类中,则添加 //异常是OK的。如下面的event()和rainHard() // void event()throws RainedOut {} public void rainHard() throws RainedOut {} //throws RainedOut可加可不加 //同样可以选择不抛出任何异常,即使在基类里声明了异常 public void event() {} //重载的方法能抛出继承的异常 void atBat() throws PopFoul{} public static void main(String[] args) { try{ Test8_2 t = new Test8_2(); t.atBat(); }catch(PopFoul e){ }catch(RainedOut e){ }catch(BaseballException e){} try{ Inning i = new Test8_2(); i.atBat(); }catch(Strike e){ }catch(Foul e){ }catch(RainedOut e){ }catch(BaseballException e){} finally{ //无论捕捉到还是捕捉不到亦或没有异常,finally总会执行 //如果违例不在catch中捕获,finally会在违例控制机制转 //到更高级别搜索一个控制器之前得以执行 } } } /* 用违例做下面这些事情: (1) 解决问题并再次调用造成违例的方法。 (2) 平息事态的发展,并在不重新尝试方法的前提下继续。 (3) 计算另一些结果,而不是希望方法产生的结果。 (4) 在当前环境中尽可能解决问题,以及将相同的违例重新“掷”出一个更高级的环境。 (5) 在当前环境中尽可能解决问题,以及将不同的违例重新“掷”出一个更高级的环境。 (6) 中止程序执行。 (7) 简化编码。若违例方案使事情变得更加复杂,那就会令人非常烦恼,不如不用。 (8) 使自己的库和程序变得更加安全。这既是一种“短期投资”(便于调试),也是一种“长期投资”(改 善应用程序的健壮性) */ 运行结果: 无