一、前言
我们在开发中最常见的异常就是NullPointerException,防不胜防啊,相信大家肯定被坑过!
这种基本出现在获取数据库信息中、三方接口,获取的对象为空,再去get出现!
解决方案当然简单,只需要判断一下,不是空在去后续操作,为空返回!
所有在JDK8时出现了专门处理的方案,出来很早了,但是小编惭愧一直没有去使用它!
最近在看《Java开发手册》,一直想着提高自己的代码水平,文中就指出了使用Optional来解决NullPointerException!
二、Java开发手册规范
小编使用的是2022版的黄山版,29页写到:
【推荐】防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
- 返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE
反例:public int method() { return Integer 对象; },如果为 null,自动解箱抛 NPE。
- 数据库的查询结果可能为 null。
- 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
- 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
- 对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。
- 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
正例:使用 JDK8 的 Optional 类来防止 NPE 问题。
这份手册还是不错的,推荐反复阅读,虽然进不去大厂,也要自觉约束自己的代码风格,努力向大厂靠!
大家现在不知道哪里找的可以下载一下:
《Java开发手册》
三、Optional常用方法
小编带大家一起从api文档中的方法,一个个带大家慢慢去了解它!
1. empty()
返回一个空的Optional实例:Optional.empty
- Optional<Object> empty = Optional.empty();
- log.info("empty值:{}",empty);
复制代码
2. of(T value)
传入一个参数,返回一个Optional对象,如果参数为空,报NullPointerException!
- Test testNew = new Test();
- Test test = null;
- Optional<Test> optionalNew = Optional.of(testNew);
- log.info(" optional对象:{}",optionalNew);
- Optional<Test> optional = Optional.of(test);
复制代码
源码查看:
我们看到参数为空会报NullPointerException,我们去方法内部看一下就明白了:- public static <T> Optional<T> of(T value) {
- return new Optional<>(value);
- }
- private Optional(T value) {
- this.value = Objects.requireNonNull(value);
- }
- public static <T> T requireNonNull(T obj) {
- if (obj == null)
- throw new NullPointerException();
- return obj;
- }
复制代码 我们发现是在Objects类中的requireNonNull方法中判断了是否为空!
这个还会出现NullPointerException,所以我们一般使用下面的这个方法!
3. ofNullable(T value)
参数传入一个对象,返回一个Optional对象,如果为空,将返回一个空的Optional对象,就等于Optional.empty
- Test testNew = new Test();
- Test test = null;
- Optional<Test> optionalNew = Optional.of(testNew);
- log.info(" optional对象:{}",optionalNew);
- Optional<Test> optionalTest = Optional.ofNullable(test);
- log.info(" optional对象中的ofNullable方法返回值:{}",optionalTest);
- Optional<Test> optionalTestNew = Optional.ofNullable(testNew);
- log.info(" optional对象中的ofNullable方法new返回值:{}",optionalTestNew);
复制代码
源码查看:
我们发现是在方法开始进行非空判断,再去调用上面的of(T value)方法- public static <T> Optional<T> ofNullable(T value) {
- return value == null ? empty() : of(value);
- }
复制代码 4. get()
如果此Optional中存在值,则返回该值,否则抛出NoSuchElementException。
- Test testNew = new Test();
- Test test = null;
- Optional<Test> optionalNew = Optional.of(testNew);
- log.info(" optional对象:{}",optionalNew);
- // Optional<Test> optional = Optional.of(test);
- Optional<Test> optionalTest = Optional.ofNullable(test);
- log.info(" optional对象中的ofNullable方法返回值:{}",optionalTest);
- Optional<Test> optionalTestNew = Optional.ofNullable(testNew);
- log.info(" optional对象中的ofNullable方法new返回值:{}",optionalTestNew);
- Test test2 = optionalTestNew.get();
- log.info("原来有值的:经过Optional包装后get后得到原来的值:{}",test2);
- Test test1 = optionalTest.get();
- log.info("原来没有值的:经过Optional包装后get后得到原来的值:{}",test1);
复制代码
源码查看:
调用开始会进行值判断,如果为空则抛异常!- public T get() {
- if (value == null) {
- throw new NoSuchElementException("No value present");
- }
- return value;
- }
复制代码 5. isPresent()
如果存在值,则返回true,否则返回false。
这里代码就不加上面的,大家参考上面的获取一个Optional对象- boolean present = optionalTestNew.isPresent();
- log.info("optionalTestNew调用是否为空:{}",present);
- boolean present1 = optionalTest.isPresent();
- log.info("optionalTest调用是否为空:{}",present1);
复制代码
源码查看:
这就比较简单了!- public boolean isPresent() {
- return value != null;
- }
复制代码 6. ifPresent(Consumer |