java异常处理技巧与原则总结

来源:互联网 发布:数据库的数据采集 编辑:程序博客网 时间:2024/05/18 03:32

java的异常处理涉及到程序流程的跳转,所以,虚拟机需要保存程序的执行流程,以便异常发生时能正确的跳转,这也就导致了使用异常时会引起额外的开销,所以,要谨慎地使用异常。
    使用异常有如下几个原则:
    1、尽量避免使用异常,将异常情况提前检测出来。
    2、不要为每个可能会出现异常的语句都设置try和catch。
    3、避免在方法中抛出(throw)或者捕获(catch)运行时异常RuntimeException和Error。
    4、避免总是catch Exception或Throwable,而要catch具体的异常类。这样可以使程序更加清晰。
    5、不要压制、隐瞒异常。将不能处理的异常往外抛,而不是捕获之后随便处理。
    6、不要在循环中使用try...catch,尽量将try...catch放在循环外或者避免使用。
    7、在catch Exception中不只要处理异常,有时还要出栈、对前面的一些变量进行处理,否则可能出现bug
    演示实例

   package book.exception;

import java.util.Date;
import java.util.EmptyStackException;
import java.util.Stack;

/** *//**
* 使用异常的几点注意
* @author joe
*
*/

public class ExceptionTips ...{
   
    public static void main(String[] args) ...{
       
        //(1)尽量避免使用异常,将异常情况提前检测出来
        Stack<Object> stack = new Stack();
        try...{
            stack.pop();
        } catch (EmptyStackException e) ...{
            //....
        }
        //应该用下面的方式,以避免使用异常
        if (!stack.isEmpty()) ...{
            stack.pop();
        }
       
        //(2)不要为每个可能会出现的一场的语句都设置try和catch
        try...{
            stack.pop();
        } catch (EmptyStackException e) ...{
            //....
        }
        String data = "123";
        try ...{
            Double.parseDouble(data);
        } catch(NumberFormatException e)...{
            //....
        }
        //应该使用下面的方式,将两个语句放在一个try块中
        try...{
            stack.pop();
            Double.parseDouble(data);
        } catch(EmptyStackException e) ...{
            //....
        } catch(NumberFormatException e) ...{
            //....
        }
       
        //(3)避免在方法中抛出或者捕获运行时异常RuntimeException和Error,
        //比如内存错误等
        //避免出现下面的情况
        String[] array;
        try ...{
            array = new String[1000];
            //array = new String[1000000];此时会出现OutOfMemoryError异常
        } catch (OutOfMemoryError e) ...{
            throw e;
        }
        //直接用下面代码
        array = new String[1000];
       
        //(4)避免总是catch Exception或Throwable,而要捕获具体的异常
        //这样可以根据不同的异常做不同的处理,使程序更加清晰
        try ...{
            stack.pop();
            Double.parseDouble(data);
        } catch (Exception e) ...{
            //应该避免catch Exception !!!
        }
       
        //(5)不要压制、隐瞒异常。将不能处理的异常往外抛,而不是捕获之后随便处理
        try...{
            Double.parseDouble(data);
        } catch (NumberFormatException e) ...{
            //.....
            throw e;    //抛出不能处理的异常,而不是隐瞒
        }
       
        //(6)不要在循环中使用try catch,尽量将try catch放在循环外或者避免使用try catch
        //下面的例子在循环中使用try和catch将耗费更多的时间,尽管没有异常发生
        int i = 0;
        int ntry = 1000000;
        Stack s = new Stack();
        long s1;
        long s2;
        System.out.println("Testing for empty stack");
        s1 = new Date().getTime();
        for (i = 0; i <= ntry; i++) ...{
            if (!s.empty()) ...{
                s.pop();
            }
        }
        s2 = new Date().getTime();
        System.out.println((s2 - s1) + "milliseconds");
       
        System.out.println("Catching EmptyStackException");
        s1 = new Date().getTime();
        for(i = 0; i<=ntry; i++) ...{
            try ...{
                s.pop();
            } catch(EmptyStackException e) ...{
            }
        }
        s2 = new Date().getTime();
        System.out.println((s2 - s1) + "milliseconds");
    }

}
程序输出:


Testing for empty stack
63milliseconds
Catching EmptyStackException
1922milliseconds

这样的错误以前我也犯过,也见过不少人这样的写法!下面我也举个例子:
 


 public void writeFile(File f) {
  String content = null;
  try {
   byte[] b = new byte[1024];
   FileInputStream in = new FileInputStream(f);
   in.read(b);
   content = new String(b);
  } catch (Exception e) {
   System.out.println(e.getMessage());
  }

  if (content.indexOf("hello") > -1) {
   System.out.println("yes");
  } else {
   System.out.println("no");
  }
 }


 上面是个简单的方法,代码中有个隐藏的bug。我在维护一个系统的时候就遇到类似的代码,实际中类似的BUG隐藏
的更深!在对系统业务和代码不是很很熟悉的情况下,我推荐如下写法:


  public void writeFile(File f) {
   String content = null;
   try {
    byte[] b = new byte[1024];
    FileInputStream in = new FileInputStream(f);
    in.read(b);
    content = new String(b);
   } catch (Exception e) {
    content="";
   //如果异常发生的话,content可能为空
   //下面对content的操作就有可能发生NullPointerException异常
   System.out.println(e.getMessage());
  }
  //下面操作有可能发生NullPointerException异常
  if (content.indexOf("hello") > -1) {
   System.out.println("yes");
  } else {
   System.out.println("no");
  }
 }