Last active
July 20, 2018 02:18
-
-
Save icella/7b56f10851dcf69a262dbb26b3578841 to your computer and use it in GitHub Desktop.
消失的异常
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Bad code. Lose NumberFomatException, but throw ArithmeticExcption | |
public class DisappearedException { | |
public void show() throws BaseException{ | |
try{ | |
Integer.parseInt("Hello"); | |
}catch (NumberFormatException nfe) { | |
throw new BaseException(nfe); | |
} finally { | |
try { | |
int result = 2 / 0; | |
} catch (ArithmeticException ae) { | |
throw new BaseException(ae); | |
} | |
} | |
} | |
} | |
//第一种做法:抛出 try 语句块中产生的原始异常的示例 | |
public class ReadFile { | |
public void read(String filename) throws BaseException{ | |
FileInputStream input = null; | |
IOException readException = null; | |
try { | |
input = new FileInputStream(filename); | |
} catch (IOException ex) { | |
readException = ex; | |
} finally { | |
if (input != null) { | |
try { | |
input.close(); | |
} catch (IOException ex) { | |
if (readException == null) { | |
readException = ex; | |
} | |
} | |
} | |
if (readException != null) { | |
throw new BaseException(readException); | |
} | |
} | |
} | |
} | |
//第二种做法:使用 addSuppressed 方法记录异常 | |
public class ReadFile { | |
public void read(String filename) throws IOException{ | |
FileInputStream input = null; | |
IOException readException = null; | |
try { | |
input = new FileInputStream(filename); | |
} catch (IOException ex) { | |
readException = ex; | |
} finally { | |
if (input != null) { | |
try { | |
input.close(); | |
} catch (IOException ex) { | |
if (readException != null) { | |
readException.addSuppressed(ex); | |
} | |
else { | |
readException = ex; | |
} | |
} | |
} | |
if (readException != null) { | |
throw readException; | |
} | |
} | |
} | |
} |
对这种问题的解决办法一般有两种.参考代码ReadFile
-
一种是抛出 try 语句块中产生的原始异常 , 忽略在 finally 语句块中产生的异常 。 这么做的出发点是try 语句块中的异常才是问题的根源.
-
另外一种是把产生的异常都记录下来 。 这么做的好处是不会丢失任何异常.
在 Java7 之前 , 这种做法需要实现自己的异常类 , 而在 Java 7 中 , 利用为 Throwable类增加的addSuppressed方法.
当一个异常被抛出的时候, 可能有其他异常因为该异常而被抑制住, 从而无法正常抛出。
这时可以通过addSuppressed方法把这些被抑制的方法记录下来。
被抑制的异常会出现在抛出的异常的堆栈信息中,也可以通过getSuppressed方法来获取这些异常。
这样做的好处是不会丢失任何异常,方便开发人员进行调试
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Problem description:
开发人员对异常处理的 try-catch-finally 语句块都比较熟悉 。
如果在 try 语句块中抛出了异常 , 在控制权转移到调用栈上一层代码之前 , finally 语句块中的语句也会执行 。
但是 finally 语句块在执行的过程中 , 也可能会抛出异常 。 如果 finally 语句块也抛出了异常 , 那么这个异
常会往上传递 , 而之前 try 语句块中的那个异常就丢失了 。
代码
DisappearedException
给出了一个示例:try 语句块会抛出 NumberFormatException , 而在 finally 语句块中会抛出 ArithmeticException 。
对这个方法的使用者来说 , 他最终看到的只是 finally 语句块中抛出的 ArithmeticException , 而 try 语句中
抛出的 NumberFormatException 消失不见了 。
由于之前产生的异常丢失 , 开发人员可能无法准确定位异常的发生位置 , 造成错误的判断 。