Practical Java(重点版)之异常处理

来源:互联网 发布:怎么投诉淘宝买家 编辑:程序博客网 时间:2024/05/20 20:19

 以下是学习《Practical Java(重点版)》的笔记。

1.  认识异常控制流(exception control flow)机制。当异常发生时,会转入到以下三种的处理方式之一:

a).catch block(捕获区段)

b).finally block(终结区段)

c).calling method(调用端)

这三种方式都是异常表现的goto行为。

如果程序在try段抛出异常会发生以下事情:

a).如果同时存在catch和finally段的话,则控制流先转向catch,然后转向finally。

b).如果没有catch的话,则转向finally段。

如果程序正常退出或者异常退出,则该方法创建的对象都将会自动解决引用。

2.  绝对不可轻忽异常(Never ignore an exception)。如果一个线程的异常发生了,但是你未捕获处理的话,那么该线程将被中断。当异常发生的时候,我们可以做的事情如下:

1). 捕捉并处理它,防止它进一步传播(propagate)。

2). 捕捉并再次抛出它,这么一来它会被传播给调用端。

3). 捕捉它,然后抛出一个新异常给调用端。

4) .不捕捉这个异常,听任它传播给调用端。

对捕获的异常,最好是记录到日志中,采用printStackTrace()的方式将其写到日志中,方便今后的查找问题。异常最好是捕获,不能够什么都不做。

3.  千万不要隐藏异常。

public class HideExectionTest {

  static void hide() throws Exception {

  try {

         throw new Exception("hide");//1

      } catch (Exception e) {

         throw new Exception("catch");//2

      } finally {

         throw new Exception("Finally");//3

      }

  }

 

  public static void main(String[] args) {

      try {

         hide();

      } catch (Exception e) {

         System.out.println("In main : cathc exception " + e.getMessage());

      }

  }

}

这种情况就隐藏了异常,输出结果:

In main : cathc exception Finally

原因:1的异常被2覆盖了,而2的异常又被3覆盖了,所以只返回了3的处理异常。在这个时候可以自定义一个异常处理类,然后收集处理的异常信息,最后再将该异常抛出。这样就避免了隐藏异常。

4.  throws子句的缺点

throws(抛掷)子句是一种语言机制,用来列出「可从某个函数传至外界」的所有可能异常。编译器强迫你必须在函数中捕捉这些被列出的异常,否则就得在该函数的throws子句中声明它们。throws子句用来向函数调用者发出预警,告知将会产生哪些异常。这是一项非常有用的语言特性,为函数用户提供非常有价值的信息。然而这个特性也有副作用,你必须心理有数。

5. 全面理解throws子句

提供throws 子句的用意在于,提醒函数调用者,告知可能发生的异常。如果父类方法throws了异常,那么子类在覆写此方法时候:可以不throws异常;可以throws出父类方法异常类的派生异常;如果在子类中出现了其他异常,则必须在子类中捕获处理,不能够传递。

如下:

class Test{

    public void key() throws FileNotFoundException{ 

    }

}

子类:

class SubTest1 extends Test{

    public void key() throws FileNotFoundException{

    }

}

class SubTest2 extends Test{

    public void key(){

    }

}

class SubTest3 extends Test{

    public void key() throws FileNotFoundException{

    try {

           …

       } catch (NumberFormatException e) {

       }

    }

}

6. 使用finally避免资源泄露

无论是否发生异常,finally中的内容始终会执行。

7. 不要在try段中返回

在try finally搭配中,最好不在try中使用return,break,continue,会导致代码阅读性不好。

以下是个例子:

public class TryFinally {

    static int test1() {

       try {

           return 1;

       } catch (Exception e) {

           return 2;

       }

    }

 

    static int test2() {

       try {

           return 3;

       } catch (Exception e) {

           return 0;

       } finally {

           return 4;

       }

    }

 

    public static void main(String[] args) {

       System.out.println(test1());

       System.out.println(test2());

    }

}

输出结果:1

                  4

8. 将try/catch段设置于循环之外

如果客户使用无JIT能力的JVM时候,将try/catch放到循环中,会导致效率下降。不启动JIT可以减少内存使用。

如果你想在不启动JIT 的情况下执行名为Test.class 的文件,请下这个命令

Java - Djava.compiler=NONE Test

这会使得在执行程序Test 时,JVM 的JIT 能力被抑制。

9.  不要将异常用于流程控制

10.不要每逢出错就使用异常

11. 在构造方法(constructors)中抛出异常

构造方法支持throws子句。

12. 抛出异常之前先将对象恢复为有效状态(valid state)

和事务有很大的相似之处,都是万一失败的话,以前提交的动作该如何处理。

 

原创粉丝点击