你能烦人( 二 )

紧接着运行maven,对项目进行编译 。
mvn clean compile findbugs:findbugs

你能烦人

文章插图
可以看到,findbugs 发现可能会在运行期间出现 NPE 后,中断了项目构建过程 。
我们再打开 findbugs 的界面看看具体的报错位置:
你能烦人

文章插图
你瞧,findbugs 准确的找到了可能出现 NPE 的根源 。
通过以上这些手段,我们尽可能的将 NPE 提前到编译期发现 。
但是啊但是,对一个规模庞大且复杂的项目来说,光使用静态代码检查还是不够的 。因为类似 findbugs 这种的静态代码检查工具 , 不可能对每个 NPE 的检查点都检查到位 。并且,探测的问题有时候因为业务原因,也会放松检查要求 。
别慌 , 我们可以让静态代码检查再加上一些别的方法,来联手堵住 NPE 问题,这就是我们下面要说的 Optional 。
4. 用 Optional 去除二义性
由于铺天盖地的 null 检查,使得 Java 程序员叫苦不堪 。于是官方自 Java8 起 , 参考了 google 的 guava,引入了 Optional 类型用来避免每次繁琐丑陋的 null 检查 。
Optional 本质上就是一个容器,这个容器持有了一个变量类型为 T 的值 。所以,Optional 这个容器中的值只会有两种情况,要么为类型 T 的变量值,要么为null 。
对于可能出现的为 null 的情况,Optional 本身从创建、检查,到抽取、使用 , 都提供了对应的方法供使用者调用 。并采用了意义很明确的方法去排除了null的二义性 。
我们看示例代码:
class Player{ private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}public class Optional4NPE { public static void main(String[] args) { Optional<Player> optiOnalPlayer= Optional.ofNullable(null); optionalPlayer.ifPresent(u -> System.out.println(u.getName())); }}以上代码我们使用了一个 Optional 中的 ofNullable,去创建了一个包含了类型为 Player、值为 null 的 Optional 容器 。
运行结果:
'Process finished with exit code 0'
运行后,代码没有任何输出,也没有出现 NPE 异常 。没有输出的原因是我们传入了一个 null 值 , 这个 null 表示值不存在 。此时,我们调用 Optional 的 ifPresent 方法做了判断,只有存在值时,才会执行打印输出 。
接下来,我们把 null 替换成有意义的值看看 。
import java.util.Optional;class Player{ private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}public class Optional4NPE { public static void main(String[] args) { Player player = new Player(); player.setId(1); player.setName("demoUser"); Optional<Player> optiOnalPlayer= Optional.ofNullable(player); optionalPlayer.ifPresent(u -> System.out.println(u.getName())); }}输出结果:
demoUserProcess finished with exit code 可以看到,当传入一个我们创建的 player 时 , 执行了打印输出方法 。
上面我们已经发现,通过 Optional 的 ifPresent 方法,我们明确了 null 的含义,明确认定只要值为 null , 就表示不存在 。那如果一个变量存在,但是没有值或者没有有意义的值呢?
我们把代码改改:
import java.util.Optional;class Player{ private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}public class Optional4NPE { public static void main(String[] args) { Player player = null; Player defaultPlayer = new Player(); defaultPlayer.setId(1); defaultPlayer.setName("————undefinedNAME-----"); Player player1 = Optional.ofNullable(player).orElse(defaultPlayer); System.out.println(player1.getName()); }}运行结果如下:
————undefinedNAME-----Process finished with exit code 0这里可以看到,我们使用 orElse 方法,当一个变量值为 null 时 , 返回一个默认值 。通过返回默认值 , 我们明确了 null 的另外一个含义,对象存在,但是可能没有实际意义 。
Optional 的出现,大大改善了我们的 Java 代码质量,减少了 NPE 的可能性,并使得代码的可读性大大增强 。
通过使用 Optional,开发人员还能非常自然轻松的使用 Null Object Pattern 模式去处理 Null 问题 。Optional 是非常值得在项目中大范围使用的 。


推荐阅读