《姐,今天我教你几个异常处理的最佳实战经验,让你以后开发不挖坑。》我笑着看着三姐解释。“好的,二哥,我洗耳恭听。”三姐也微微一笑,欣然收下。“行了,哥哥不废话了,我们开始吧。”1)尽量不要捕获RuntimeException阿里出品的嵩山版Java开发手册中规定:尽量不要捕获RuntimeException,比如NullPointerException、IndexOutOfBoundsException等,应该使用预检的方式来避免。正例:if(obj!=null){//...}反例:try{obj.method();}catch(NullPointerExceptione){//...}“哦,如果有一些异常不能预检什么?”三姐问道。“确实会出现这样的情况,比如NumberFormatException,虽然也是RuntimeException,但是没有办法预先检查,所以应该用catch来捕获和处理。”我说。2)尽量使用try-with-resource关闭资源当需要关闭资源时,尽量不要使用try-catch-finally,禁止直接在try块中关闭资源。反例:publicvoiddoNotCloseResourceInTry(){FileInputStreaminputStream=null;try{Filefile=newFile("./tmp.txt");inputStream=newFileInputStream(file);inputStream.close();}catch(FileNotFoundExceptione){log.error(e);}catch(IOExceptione){log.error(e);}}“为什么?”三姐问。“原因也很简单,因为一旦在close()之前发生异常,资源就无法关闭,直接使用try-with-resource来处理是最好的方式。”我说。publicvoidautomaticallyCloseResource(){Filefile=newFile("./tmp.txt");try(FileInputStreaminputStream=newFileInputStream(file);){}catch(FileNotFoundExceptione){log.error(e);}catch(IOExceptione){log.error(e);}}“除非资源没有实现AutoCloseable接口。”我补充道。“那这种情况我们该怎么办?”三姐问道。“只需关闭finally块中的流,”我说。publicvoidcloseResourceInFinally(){FileInputStreaminputStream=null;try{Filefile=newFile("./tmp.txt");inputStream=newFileInputStream(file);}catch(FileNotFoundExceptione){log.error(e);}finally{if(inputStream!=null){try{inputStream.close();}catch(IOExceptione){log.error(e);}}}}3)不捕获ThrowableThrowable是异常和错误的父类,如果捕获在catch子句Throwable,很可能捕捉到超出程序处理能力的错误。publicvoiddoNotCatchThrowable(){try{}catch(Throwablet){//不要这样做}}“到底为什么?”三姐问。"因为有些错误不需要程序处理,程序可能无法处理,比如OutOfMemoryError或者StackOverflowError。前者是Java虚拟机无法申请到足够的内存空间时出现的异常错误,而后者是由于线程申请,如果堆栈深度超过最大允许异常错误,如果被捕获,将掩盖程序应该发现的严重错误。我说。“比如一匹马只能拉一节车厢的货物,可能挂两节车厢,但一旦被抓住,就找不到问题了。”我补充道。4)不要遗漏异常信息的记录。很多时候,由于疏忽,开发人员很容易捕获到异常,却没有记录异常信息。结果,程序上线后确实出现了问题,但没有记录可查。publicvoiddoNotIgnoreExceptions(){try{}catch(NumberFormatExceptione){//没有记录异常}}应该记录错误信息。publicvoidlogAnException(){try{}catch(NumberFormatExceptione){log.error("Oh,anerrorhappened:"+e);}}5)不记录异常,不抛异常。这纯属多此一举,容易造成误导。反例:try{}catch(NumberFormatExceptione){log.error(e);throwe;}想扔就扔,不要记录,记录了再扔,没必要。反例:publicvoidwrapException(Stringinput)throwsMyBusinessException{try{}catch(NumberFormatExceptione){thrownewMyBusinessException("错误信息描述:",e);}}这个道理是一样的,既然已经被捕获了,就不要再抛了方法签名。6)不要在finally块中使用return。根据阿里出品的松山Java开发手册,try块中的return语句执行成功后,不会立即返回,而是继续执行finally块中的语句。如果finally块中的try块中也有return语句,那么try块中的return将被覆盖。反例:privateintx=0;publicintcheckReturn(){try{return++x;}finally{return++x;}}“哦,确实,try块中x返回的值为1,它返回2在finally块中就没有了。”三姐说道。“这是正确的。”我点了头。“好了,三妹,先说说这6个异常处理的做法吧,在实际开发中,你还会遇到一些其他的坑,如果你自己去踩一下,可能印象会更深刻。”我说。“那下班被老板骂了怎么办?”三姐委屈的说道。“一个新人,写出几个bug才对得起新人的称号。”我淡淡的说道。“好的。”三姐无奈的叹了口气。本文转载自微信公众号“沉默王二”,可通过以下二维码关注。转载本文请联系沉默王二公众号。
