首页 > 编程语言 >《Effective Java》阅读笔记-第十章

《Effective Java》阅读笔记-第十章

时间:2024-02-21 16:25:01浏览次数:45  
标签:Java Effective 受检 抛出 第十章 使用 catch 异常

Effective Java 阅读笔记

第十章 异常

第 69 条 只针对异常的情况才使用异常

说白了就是不要吧你的业务逻辑用异常来写。

举个反例

比如用抛出异常来遍历一个数组:

try {
    int i = 0;
    while(true) {
        range[i++].doSomething();
    }
} catch (ArrayIndexOutOfBoundsException e) {

}

这种代码我只想说,那你可真是可小天才。

通常来说:

  • 异常应该只适用于出现异常的情况下,它永远不应该用于正常的控制流。
  • 设计良好的 API 不应该强迫调用者为了正常的控制流而使用异常。

比如Iterator<T>接口,这个接口有一个next()取值方法和hasNext()检测方法,这样就可以使用传统 for 循环(以及 for-each,因为内部使用了 hasNext)的调用成为可能:

Collection<String> collection = new ArrayList<>();
for (Iterator<String> iter = collection.iterator(); iter.hasNext(); ) {
    String next = iter.next();
}

否则只能使用异常去进行流程控制:

Iterator<String> iterator = collection.iterator();
try {
    while (true) {
        String next = iterator.next();
    }
} catch (NoSuchElementException e) {
    
}

这一点深有同感,特别是在对比 C# 和 Java 的之后,Java 中在进行类型转换的时候,比如字符日转换成 Integer 或者 Double 之类的,没有 TryParse 方法,C# 就提供了这样的方法。

第 70 条 对可恢复的错误使用受检异常,对编程错误使用运行时异常

Java 中提供了三种可抛出结构(Throwable):受检异常(checked exception)、运行时异常(runtime exception)、错误(error)。

一般来说,如果期望调用者能够适当地回复(recover),那么就用受检异常。而运行时异常通常来表名编程错误,比如访问了业界的下标,就会抛出数组越界异常。
同时,自己实现的所有未受检异常都应该是RuntimeException的子类,不应该定义或者抛出 Error 的子类,Error 一般是虚拟机无法处理的时候就会抛出 Error。

第 71 条 避免不必要地使用受检异常

收件异常强迫调用者去处理异常情况,这会使 API 非常难以使用。

当且仅当万一失败,并且还无法提供足够的信息时,才抛出受检异常。

第 72 条 优先使用标准的异常

标准库中定义了许多较为通用的异常,使用这些异常会使 API 更容易学习和使用,并且可读性也会更好。

但是不要直接重用 Exception、RuntimeException、Error。

这是一些常用异常:

异常 使用场合
IllegalArgumentException 非 null 的参数值不正确
IllegalStateException 不合适的调用状态
NullPointerException 禁止使用 null 的情况下参数为 null
IndexOutOfBoundsException 下标参数值越界
ConcurrentModificationException 禁止并发修改的情况下检测到了并发修改
UnsupportedOperationException 对象不支持用户请求的方法

一般来说,不要自己编写异常类。

第 73 条 抛出与抽象对应的异常

如果抛出的异常和它执行的任务没有直接关系,会让人感到困惑、不知所措。

因此更高层的实现应该捕获底层的异常,同时可以抛出按照高层抽象进行解释的异常,这叫异常转译(exception translation)。

比如:

// 异常转译(exception translation)
try {
    // 内部处理抛出了低等级异常
} catch (LowerLevelException e) {
    throw new HigherLevelException(...);
}

尽管转译相对直接抛出低级异常有优势,但是也不能滥用。

第 74 条 每个方法抛出的所有异常都要建立文档

文档中始终要单独声明受检异常,并记录下每个异常的抛出条件。

使用 Javadoc 的@throws标签记录方法可能抛出的所有异常,不要在方法签名上写未受检异常。

第 75 条 将失败捕获信息添加到异常详细信息中

主动抛出异常时,异常中除了包含堆栈信息,还可以添加自定义的消息,方便查找问题。

第 76 条 失败应保持原子性

一般而言,方法调用失败时应该使对象保持在被调用之前的状态,这叫原子性失败(failure atomic)。

第 76 条 不要忽略异常

空的 catch 块会使异常不能达到应有目的,也就是强迫你进行处理。

如果选择忽略异常,catch 块中应包含一条注释,说明为什么可以这样做,并将异常变量命名为 ignored:

Future<Integer> f = exec.submit(planarMap::chromaticNumber)
int numColors = 4; // 默认值
try {
    numColors = f.get(1L, TimeUnit.SECONDS);
} catch (TimeoutException | ExecutionException ignored) {
    // 使用默认值,颜色设置是可选的,非必须的。
}

标签:Java,Effective,受检,抛出,第十章,使用,catch,异常
From: https://www.cnblogs.com/code-blog/p/18025533

相关文章

  • 《Effective Java》阅读笔记-第十二章
    EffectiveJava阅读笔记第十二章序列化第85条其他方法优先于Java本身的序列化Java本身的序列化漏洞过多,很容易被攻击。避免被序列化攻击的最好方式就是不要反序列化任何字节流,并且新的系统中没有任何理由使用Java本身的序列化。JSON和Protobuf是两种优秀的序列化......
  • java类初始化及代码块加载顺序连根拔起
    说明相信很多人对于java中父子继承关系中,子类实例化调用过程中,代码块的执行顺序都容易忘记或搞混,尤其是java初级笔试题或面试题最容易出这类题目,让人恨得牙痒痒!!!本文就一次性将其连根铲除,看完你就不会有这个烦恼了,哈哈。先引用一下骨灰级大作《Java编程思想》的复用章节Java......
  • 一键脚本破解最新版 idea 步骤,开启学习java 之旅,好好好
    效果:步骤1、idea安装:直接在官网下载最新idea-2022.2.3.dwg(:官网地址,然后根据安装引导一步一步完成安装即可,完成后打开idea看到如下效果表示idea安装成功!如图发现idea需要注册!这里我们先不管,直接关闭idea准备激活!步骤2、下载最新的破解包https://pan.baidu.com/s/1iQby9......
  • Hutool - 简化Java编程的法宝,让工作更高效
    一、在项目的pom.xml的dependencies中加入以下内容:<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.0.7</version></dependency>非Maven项目的话就自己百度下载一下jar包,导入即可。二、StrUtil看这里名字也应该明白了,......
  • 承前启后,Java对象内存布局和对象头
    承前启后,Java对象内存布局和对象头大家好,我是小高先生。在我之前的一篇文章《并发编程防御装-锁(基础版)》中,我简要介绍了锁的基础知识,并解释了为什么Java中的任何对象都可以作为锁。在那里,我提到了对象头中有一个指向ObjectMonitor的指针,但没有深入探讨Java对象的内存结构。本文将......
  • Java的配置
    环境变量配置找到配置的位置右击此电脑-->属性-->高级系统设置-->环境变量-->系统变量配置Path环境变量(必须配置的)(目的:为了可以在任意目录下找到javac和java命令)方式1:直接在Path变量中添加jdk的bin目录的完整路径系统变量-->Path-->新建-->D:\soft\java\jdk\bin方式2:(推荐......
  • java练习2(四位数字进行加密)
    packagecom.shujia.zuoye;importjava.util.Scanner;/*某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下:每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换。结果如图所示。*/publicclass加密......
  • java练习1(求圆的周长与面积)
    packagecom.shujia.zuoye;importjava.util.Scanner;/*输入圆形半径,求圆形的周长和圆形的面积,并将结果输出。/publicclass求圆的面积{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);System.out.println("请输入圆的半径:");doubler=s......
  • 在阿里云部署javaspringboot项目
    记住自己服务器的账号密码配置安全组  用xshell连接服务器(xftp同理) 到官网去下载jdk的Linux版本,官网地址:https://www.oracle.com/technetwork/java/javase/downloads 安装JDK我自己用的是jdk21,下载完毕后用xftp传到服务器上(解压一下)#tar-zxvf压缩包.tar.......
  • java~Date和LocalDateTime及Instant的使用场景
    在Java中,LocalDateTime、Date和Instant分别代表了不同的日期时间类型,它们之间有一些区别和适用场景。Date:java.util.Date是Java早期的日期时间类,它包含了日期和时间信息,但是在设计上存在一些问题,因此并不推荐在新的代码中使用。Date类存在线程安全性问题,同时它的......