译者:潘潘
前言
本文总结了有关Java异常的十大常见问题。
目录
- 检查型异常(checked) vs. 非检查型异常(Unchecked)
- 异常管理的最佳实践箴言
- 为什么在try代码块中声明的变量不能在catch或者finally中被引用?
- 为什么 Double.parseDouble(null) 和 Integer.parseInt(null) 抛出的异常不一样呢?
- Java中经常使用的运行时异常
- 我们可以在同一个catch子句中捕获多个异常吗?
- 在 Java 中构造方法能抛出异常吗?
- 在 final 代码块中抛出异常
- try语句有return那么finally还会执行吗?
- 为何有些开发人员对异常置之不理?
1.检查型异常(checked) vs 非检查型异常(Unchecked)
简单来说,对于检查型异常, 一般在编译期就会被检查到,所以我们肯定会提前在方法内进行捕获处理,或者在方法头部申明并抛出。而非检查型异常,往往无法提前预知,例如被除数是0、空指针等。检查型异常特别重要,它会告诉那些调用你的接口的开发者们,如何提前预知并处理好这些可能发生的异常。
例如,IOException就是常见的检查型异常,而 RuntimeException(运行时异常)就是非检查型异常。在阅读剩余部分之前你或许可以研读这份Java异常的层次结构图。
2.异常管理的最佳实践箴言
如果可以正确处理异常,则应将其捕获并处理,否则应将其抛出。
3. 为什么在try代码块中声明的变量不能在catch或者finally中被引用?
看下面这段代码,在try代码块中声明的String s就不能在catch中被引用, 这段代码在编译期是通不过的。
try{
File file =newFile("path");
FileInputStream fis =newFileInputStream(file);
String s ="inside";
}catch(FileNotFoundException e) {
e.printStackTrace();
System.out.println(s);
}
原因是你不知道在try代码块中哪个位置会引发异常, 很有可能在声明对象之前就引发了异常。对于这个特定的示例,是正确的。
4.为什么 Double.parseDouble(null) 和 Integer.parseInt(null) 抛出的异常不一样呢?
它俩抛出的异常确实不同,但这是JDK的问题,当时开发这两个接口的开发人员不是同一波,所以我们没必要去纠结这个问题。
Integer.parseInt(null);// throws java.lang.NumberFormatException: nullDouble.parseDouble(null);// throws java.lang.NullPointerException
5.Java中经常使用的运行时异常
这里列举一部分:
IllegalArgumentException ArrayIndexOutOfBoundsException
在有些场景某个目标对象不满足我们的预期,会用到这些异常,例如下面在 if 判断语句中被使用:
if(obj ==null) {thrownewIllegalArgumentException("obj can not be null");
6.我们可以在同一个catch子句中捕获多个异常吗?
答案是当然可以,不过如果在同一个catch子句中捕获的这些异常都直接或间接继承自同一父类,那么就只能在catch子句中捕获父类了。
// Java 7 之前需要这样catch(AException a) {
logger.error(a);thrownewMyException("a");catch(BException b) {
logger.error(b);thrownewMyException("b");
}catch(CException c) {
logger.error(c);thrownewMyException("c");
}// 在Java 7中,可以捕获所有这些异常catch(AException | BException | CException ex){
logger.error(ex);thrownewMyException(ex);
}
补充说明 : 其实是这样,在 Java7 就开始支持catch子句捕获多个异常,多个异常使用XOR符号(I)连接,异常的发生有可能是 A | B,但不能同时出现,相当于这些异常不能是间接或直接继承自同一个父类,因为如果AB都继承同一父类,那就不能 A|B 都写上,这也是继承原则。
7.在 Java 中构造方法能抛出异常吗?
答案是当然可以,构造方法仅是一种特殊方法而已。可以参考这个示例。
classFileReader{publicFileInputStream fis =null;publicFileReader()throwsIOException{
File dir =newFile(".");//get current directoryFile fin =newFile(dir.getCanonicalPath() +
File.separator +"not-existing-file.txt");
fis =newFileInputStream(fin);
}
}
8.在 final 代码块中抛出异常
下面这个写法是合法的:
publicstaticvoidmain(String[] args){
File file1 =newFile("path1");
File file2 =newFile("path2");try{
FileInputStream fis =newFileInputStream(file1);
}catch(FileNotFoundException e) {
e.printStackTrace();
}finally{try{
FileInputStream fis =newFileInputStream(file2);
}catch(FileNotFoundException e) {
e.printStackTrace();
}
}
}
但是为了获得更好的代码可读性,你应该将把 try-catch代码块封装成一个新方法,然后将方法调用放在finally子句中:
publicstaticvoidmain(String[] args){
File file1 =newFile("path1");
File file2 =newFile("path2");try{
FileInputStream fis =newFileInputStream(file1);
}catch(FileNotFoundException e) {
e.printStackTrace();
}finally{// 封装方法methodThrowException();
}
}
9.try语句有return那么finally还会执行吗?
答案是肯定会执行。
Java官方文档描述:The finally blockalwaysexecutes when the try block exits
意思就是 只要存在try代码块,finally代码块就一定会执行 ,这种特性可以让程序员避免在try语句中使用return, continue或者break关键字而忽略了关闭相关资源的操作等。
10.为何有些开发人员对异常置之不理?
很多时候会见到下面这种代码写法。允许的情况下尽可能捕获异常并且进行处理,不知道为什么很多开发人员就是这么干?
try{
...
}catch(Exceptione) {
e.printStackTrace();
}
忽略异常是一件很容易做到的事,虽然这种写法很常见,但不一定是正确的写法。
参考文献:
- Unchecked exceptions in Java
- The root of Java exception class hierarchy
- Java exceptions related questions in stackoverflow
译文完,由于个人理解能力和知识宽度有限,译文中存在失误之处,还请见谅,欢迎指正。
声明:本文部分素材转载自互联网,如有侵权立即删除 。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容