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 stack63millisecondsCatching EmptyStackException1922milliseconds
这样的错误以前我也犯过,也见过不少人这样的写法!下面我也举个例子:
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"); } }
本文来自博客,转载请标明出处:http://blog.csdn.net/linweidong/archive/2010/11/05/5989889.aspx