封面:洛小汐

译者:潘潘

知彼知己,方能百战不殆。

前言

本文总结了有关Java异常的十大常见问题。

目录

  1. 检查型异常(checked) vs. 非检查型异常(Unchecked)

  2. 异常管理的最佳实践箴言

  3. 为什么在try代码块中声明的变量不能在catch或者finally中被引用?

  4. 为什么 Double.parseDouble(null) 和 Integer.parseInt(null) 抛出的异常不一样呢?

  5. Java中经常使用的运行时异常

  6. 我们可以在同一个catch子句中捕获多个异常吗?

  7. 在 Java 中构造方法能抛出异常吗?

  8. 在 final 代码块中抛出异常

  9. try语句有return那么finally还会执行吗?

  10. 为何有些开发人员对异常置之不理?

检查型异常(checked) vs. 非检查型异常(Unchecked)

简单来说,对于检查型异常, 一般在 编译期 就会被检查到,所以我们肯定会提前在方法内进行捕获处理,或者在方法头部申明并抛出。而非检查型异常,往往无法提前预知,例如被除数是0、空指针等。检查型异常特别重要,它会告诉那些调用你的接口的开发者们,如何提前预知并处理好这些可能发生的异常。

例如,IOException就是常见的检查型异常,而 RuntimeException(运行时异常)就是非检查型异常。在阅读剩余部分之前你或许可以研读这份 Java异常的层次结构图

异常管理的最佳实践箴言

如果可以正确处理异常,则应将其捕获并处理,否则应将其抛出。

为什么在try代码块中声明的变量不能在catch或者finally中被引用?

看下面这段代码,在try代码块中声明的 String s 就不能在catch中被引用, 这段代码在编译期是通不过的。


try {
File file = new File("path");
FileInputStream fis = new FileInputStream(file);
String s = "inside";
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println(s);
}

原因是你不知道在try代码块中哪个位置会引发异常, 很有可能在声明对象之前就引发了异常。对于这个特定的示例,是正确的。

为什么 Double.parseDouble(null) 和 Integer.parseInt(null) 抛出的异常不一样呢?

它俩抛出的异常确实不同,但这是JDK的问题,当时开发这两个接口的开发人员不是同一波,所以我们没必要去纠结这个问题。


Integer.parseInt(null);
// throws java.lang.NumberFormatException: null Double.parseDouble(null);
// throws java.lang.NullPointerException

Java中经常使用的运行时异常

这里列举一部分:

IllegalArgumentException
ArrayIndexOutOfBoundsException

在有些场景某个目标对象不满足我们的预期,会用到这些异常,例如下面在 if 判断语句中被使用:


if (obj == null) {
throw new IllegalArgumentException("obj can not be null");

我们可以在同一个catch子句中捕获多个异常吗?

答案是当然可以,不过如果在同一个catch子句中捕获的这些异常都直接或间接继承自同一父类,那么就只能在catch子句中捕获父类了。

// Java 7 之前需要这样
catch (AException a) {
logger.error(a);
throw new MyException("a");
catch (BException b) {
logger.error(b);
throw new MyException("b");
}catch (CException c) {
logger.error(c);
throw new MyException("c");
} // 在Java 7中,可以捕获所有这些异常
catch(AException | BException | CException ex){
logger.error(ex);
throw new MyException(ex);
}

补充说明 : 其实是这样,在 Java7 就开始支持catch子句捕获多个异常,多个异常使用 **XOR符号(I)**连接,异常的发生有可能是 A | B,但不能同时出现,相当于这些异常不能是间接或直接继承自同一个父类,因为如果AB都继承同一父类,那就不能 A|B 都写上,这也是继承原则。

在 Java 中构造方法能抛出异常吗?

答案是当然可以,构造方法仅是一种特殊方法而已。可以参考这个示例

在 final 代码块中抛出异常

下面这个写法是合法的:


public static void main(String[] args) {
File file1 = new File("path1");
File file2 = new File("path2");
try { FileInputStream fis = new FileInputStream(file1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
FileInputStream fis = new FileInputStream(file2);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

但是为了获得更好的代码可读性,你应该将把 try-catch代码块封装成一个新方法,然后将方法调用放在finally子句中:


public static void main(String[] args) {
File file1 = new File("path1");
File file2 = new File("path2");
try { FileInputStream fis = new FileInputStream(file1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
// 封装方法
methodThrowException();
}
}

try语句有return那么finally还会执行吗?

答案是肯定会执行。

Java官方文档描述:The finally block always executes when the try block exits

意思就是 ” 只要存在try代码块,finally代码块就一定会执行 ” ,这种特性可以让程序员避免在try语句中使用return, continue或者break关键字而忽略了关闭相关资源的操作等。

为何有些开发人员对异常置之不理?

很多时候会见到下面这种代码写法。允许的情况下尽可能捕获异常并且进行处理,不知道为什么很多开发人员就是这么干?


try {
...
} catch(Exception e) {
e.printStackTrace();
}

忽略异常是一件很容易做到的事,虽然这种写法很常见,但不一定是正确的写法。

参考文献:
  1. Unchecked exceptions in Java
  2. The root of Java exception class hierarchy
  3. Java exceptions related questions in stackoverflow

译文完,由于个人理解能力和知识宽度有限,译文中存在失误之处,还请见谅,欢迎指正。

译文《最常见的10种Java异常问题》的更多相关文章

  1. 一文学会最常见的10种NLP处理技术

    一文学会最常见的10种NLP处理技术(附资源&代码)   技术小能手 2017-11-21 11:08:29 浏览2562 评论0 算法 HTTPS 序列 自然语言处理 神经网络 摘要: 自然 ...

  2. 移动端App广告常见的10种形式

    什么是App广告?   App广告,或称In-App广告,是指智能手机和平板电脑这类移动设备中第三方应用程序内置广告,属于移动广告的子类别. App广告兴起得益于其载体—App的风行.平板电脑和大屏触 ...

  3. 常见的几种java排序算法

    一.分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配排序(基数排序) 所需辅助空间最多:归并排序 所需辅 ...

  4. java 常见的几种运行时异常RuntimeException

    常见的几种如下:   NullPointerException - 空指针引用异常ClassCastException - 类型强制转换异常.IllegalArgumentException - 传递 ...

  5. 【刷题】java 常见的几种运行时异常RuntimeException

    常见的几种罗列如下: -NullPointerException - 空指针引用异常 ClassCastException - 类型强制转换异常. IllegalArgumentException - ...

  6. 10个关于Java异常的常见问题

    这篇文章总结了十个经常被问到的JAVA异常问题: 1.检查型异常VS非检查型异常 简单的说,检查型异常是指需要在方法中自己捕获异常处理或者声明抛出异常由调用者去捕获处理: 非检查型异常指那些不能解决的 ...

  7. 常见 Java 异常解释(恶搞版)

    常见 Java 异常解释:(译者注:非技术角度分析.阅读有风险,理解需谨慎o(╯□╰)o) java.lang ArithmeticException 你正在试图使用电脑解决一个自己解决不了的数学问题 ...

  8. 10 个深恶痛绝的 Java 异常。。

    异常是 Java 程序中经常遇到的问题,我想每一个 Java 程序员都讨厌异常,一 个异常就是一个 BUG,就要花很多时间来定位异常问题. 什么是异常及异常的分类请看这篇文章:一张图搞清楚 Java ...

  9. 十个常见的Java异常出现原因

    异常是 Java 程序中经常遇到的问题,我想每一个 Java 程序员都讨厌异常,一 个异常就是一个 BUG,就要花很多时间来定位异常问题. 1.NullPointerException 空指针异常,操 ...

随机推荐

  1. 13. 从0学ARM-Cortex-A9 RTC裸机程序编写

    一.RTC RTC(Real-Time Clock) 实时时钟. RTC是集成电路,通常称为时钟芯片.在一个嵌入式系统中,通常采用RTC来提供可靠的系统时间,包括时分秒和年月日等,而且要求在系统处于关 ...

  2. 国产网络损伤仪SandStorm -- 主界面简介

    国产网络损伤仪SandStorm可以模拟出带宽限制.时延.时延抖动.丢包.乱序.重复报文.误码.拥塞等网络状况,在实验室条件下准确可靠地测试出网络应用在真实网络环境中的性能,以帮助应用程序在上线部署前 ...

  3. spring再学习之简单测试

    一.spring是怎么工作的那,通过一个类装载进容器进行描述: 首先创建一个类user: package cn.itcast.bean; public class User { public User ...

  4. SpringBoot 全局视角看springboot

    从单体架构到微服务 单体架构 任何一个网站在发布初期几乎都不可能立马就拥有庞大的用户流量和海量数据,都是在不停 的试错过程中一步一步演变其自身架构,满足其自身业务.比如现在能够抗住双十一这么大 流量的 ...

  5. 2021-2-18:请你说说MySQL的字符集与排序规则对开发有哪些影响?

    任何计算机存储数据,都需要字符集,因为计算机存储的数据其实都是二进制编码,将一个个字符,映射到对应的二进制编码的这个映射就是字符编码(字符集).这些字符如何排序呢?决定字符排序的规则就是排序规则. 查 ...

  6. SSH Keys vs GPG Keys

    SSH Keys vs GPG Keys SSH Keys SSH keys allow you to establish a secure connection between your compu ...

  7. SwiftUI & MVVM

    SwiftUI & MVVM design paradigm / 设计模式 MVVM Model View ViewModel MVVM Architecture 架构 MVC Model V ...

  8. TypeScript & React & Jest

    TypeScript & React & Jest create-react-app Jest ``tsx import React from 'react'; import { re ...

  9. html2Canvas to Images

    <script> $(function () { var content = document.getElementById("shareImages"); conte ...

  10. 下一代币王花落谁家?是否是BGV更胜一筹呢?

    BGV作为Baccarat的平台币横空出世,通过BGV来激励拥有NGK的用户.在共识算法上,Baccarat 在共识层采用了混合机制 DPOSS共识机制,这是维护 Baccarat 生态体系良性发展的 ...