Java Exception In Action

在这里插入图片描述

可检查的异常

可检查的异常Checked Exception, 所有的可检查的异常都是需要在代码中处理的, 它们的发生是可预测, 可以合理处理的. 比如IOExeption, 或者一些自定义的异常. 除了RuntimeException及其子类以外, 都是checked exception.

可检查的异常处理
  1. 捕获对应的异常, 通过日志logger打印异常信息.
  2. 捕获对应的异常, 返回和业务相关的提示信息.
  3. 如果不想处理它, 请将该异常抛给它的调用者, 最外层的业务使用者, 必须处理异常, 将其转换为用户可以理解的内容.

不可检查的异常

Java类库中定义的一类RuntimeException可以通过预先检查进行规避, 而不应该通过catch来处理, 比如IndexOutOfBoundsException, NullPointerException等等.
无法通过预检查的异常除外, 如在解析一个外部传来的字符串形式数字时, 通过catch NumberFormatException来实现.

NPE的产生
  1. 返回类型为基本类型数据, return 包装数据类型的对象时, 自动拆箱有可能产生NPE.
public int f() { return Integer 对象 }, 如果为null, 自动解箱抛NPE.
  1. 数据库的查询结果可能为null.
  2. 集合里的元素即使isNotEmpty, 取出的数据元素也可能为null.
  3. 远程调用返回对象时, 一律要求进行空指针判断, 防止NPE.
  4. 对于Session 中获取的数据, 建议NPE检查, 避免空指针.
规避NPE
  • 人们常常使用null值表示值不存在, Optional对象能更好地表达这个概念. 使用null代表值不存在的最大问题在于NullPointerException. 一旦引用一个存储null值的变量, 程序会立即崩溃.
  • 规避NPE是调用者的责任. 即使被调用方法返回空集合或者空对象, 对调用者来说, 也并非高枕无忧, 必须考虑到远程调用失败, 序列化失败, 运行时异常等场景返回null 的情况.

JAVA8的Optional类

Optional主要用作返回类型. 在获取到这个实例后, 如果他有值, 你可以取得这个值, 否则可以进行一些替代行为.
Optional是Java语言的有益补充, 它旨在减少代码中的NPE, 虽然还不能完全消除这些异常.

	// 利用Optional.isPresent()进行判空操作
	@Test
    public void whenCheckIfPresent_thenOk() {
        HelloWorld helloWorld = new HelloWorld(1, "HelloWorld");
        Optional<HelloWorld> opt = Optional.ofNullable(helloWorld);
        assertTrue(opt.isPresent());
        assertEquals(helloWorld.getHelloWorld(), opt.get().getHelloWorld());
    }
    
    // 在参数为null的情况下, 利用Optional.orElse方法提供默认值
	@Test
    public void whenEmptyValue_thenReturnDefault() {
        HelloWorld helloWorld = null;
        HelloWorld helloWorld1 = new HelloWorld(1, "HelloWorld");
        HelloWorld result = Optional.ofNullable(helloWorld).orElse(helloWorld1);

        assertEquals(helloWorld1.getHelloWorld(), result.getHelloWorld());
    }
    
    // 可以决定抛出什么异常, 而不总是抛出NPE
	@Test(expected = IllegalArgumentException.class)
    public void whenThrowException_thenOk() {
        HelloWorld helloWorld = null;
        HelloWorld helloWorld1 = Optional.ofNullable(helloWorld)
                .orElseThrow(() -> new IllegalArgumentException());
    }

预先检查

if (obj != null) {...}

Note

  1. 定义时区分unchecked/ checked 异常, 避面直接抛出new RuntimeException(), 更不允许抛出Exception 或者 Throwable, 应使用有业务含义的自定义异常.推荐业界已定义过的自定义异常, 如: DAOException / ServiceException等.
  2. 在代码中使用"抛异常"还是返回"错误码", 对于公司外的http/api开放接口必须使用错误码; 而应用内部推荐异常抛出; 跨应用间RPC调用优先考虑使用Result方式, 封装isSuccess()方法, “错误码”, “错误简短信息”.
  3. 采用日志log打印异常信息, 在生产环境中别用异常的printStackTrace()方法, printStackTrace默认会把调用的堆栈打印到控制台上, 在生产环境中访问控制台是不现实的.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值