try catch好的一面

  try catch虽然不推荐用于程序结构的控制,但是也具有重要的意义,其设计的一个好处是,开发人员可以把一件事情当做事务来处理,事务也是数据库中重要的概念,举个例子,比如完成订单的这个事务,其中包括了一个动作序列,包括用户提交订单,商品出库,关联等。当这个序列中某一个动作执行失败的时候,数据统一恢复到一个正常的点,这样不会出现,你付完了帐,商品却没有给你的情况。我们在try语句块中像执行一个事务一样,当出现了异常,会在catch中得到统一的处理,保证数据的完整无损。其实很多不好的代码也是因为没有好好利用catch语句的语言,导致很多异常被淹没了,这个后面介绍。

  定制详细的异常

  我们可以自己定义异常,以捕获处理某个具体的例子。创建自己的异常类,可以直接继承Exception或者RuntimeException。区别是前者是简称类型的,而后者为检查类型异常。Sun官方力挺传统的观点,他建议开发者都是用检查类型的异常,即你一定要去处理的异常。下面是定义的一个简单的异常类。


1.public class SimpleException extends Exception{  
2.    SimpleException(){}  
3.    SimpleException(String info){  
4.        super(info);  
5.    }  
6.}
 


  我们覆写了两个构造方法,这是有意义的。通过传递字符串参数,我们创建一个异常对象的时候,可以记录下详细的信息,这样这个异常被捕获的时候会显示我们之前定义的详细信息。比如用下面的代码测试一下我们定义的异常类:


1.public class Test {  
2.    public void fun() throws SimpleException{  
3.        throw new SimpleException("throwing from fun");  
4.    }  
5.    public static void main(String[] args) {  
6.        Test t = new Test();  
7.        try{  
8.            t.fun();  
9.        }catch(SimpleException e){  
10.            e.printStackTrace();  
11.        }  
12.    }  
13.}
 


  运行会得到下面的结果 printStackTrace是打印调用栈的方法,他有三个重载方法,默认的是将信息输出到System.err。这样我们可以清晰的看到方法调用的过程,有点像操作系统中的中断,保护现场。


SimpleException: throwing from fun
at Test.fun(Test.java:4)
at Test.main(Test.java:9)


  略微麻烦的语法

  我们自己实现的异常有时候会用到继承这些特性,在异常继承的时候有一些限制。那是子类不能抛出基类或所实现的接口中没有抛出的异常.比如有如下的接口:


1.public interface InterfaceA {  
2.    public void f() throws IOException;  
3.}
 


  我们的Test类实现这个接口,那么Test的f方法要么不抛出异常,要么只能抛出IOException,其实关于这里还有更琐碎的规矩,详细可以参考《Java Puzzlers》第37个谜题。所以这和传统的继承和实现接口正好相反,面向对象的继承是扩大化,而这正好是缩小了。