• 使用Optional优雅处理null


      先假设一个场景。如下所示

     1 public class Person {
     2 
     3     private String name;
     4 
     5     public Person() {
     6     }
     7 
     8     public Person(String name) {
     9         this.name = name;
    10     }
    11 
    12     public String getName() {
    13         return name;
    14     }
    15 }

      我们有一个Person类,有一个属性是name。有如下代码:

    1 public static void main(String[] args) {
    2     Person person = new Person();
    3 
    4     String name = person.getName();
    5 
    6     if (name.equals("Jackson")) {
    7         System.out.println("My name is Jackson!");
    8     }
    9 }

      我们判断获取person的name,然后判断person的name是不是Jackson。因为person的name为null,所以name.equals("Jackson")这段代码会报空指针的异常。

      我们有多种方式来处理空指针的异常,一种是我们考察我们的业务逻辑,当需要返回一个null值时返回一个有意义的NullObject。例如空字符串对应返回字符串的情况,空列表对应返回list的情况,对一些特殊的对象,可以根据不同的业务逻辑创建一些Null对象。参考《Effictive Java》第43条,《重构》9.7节。

      对于我们的例子,当name为null时,getName方法返回一个""字符串。当接下来取出name来进行操作时就不会出现空指针的异常。

    1 public String getName() {
    2     if (name == null) {
    3         return "";
    4     } else {
    5         return name;
    6     }
    7 }

      另一种是在调用的时候判断是否为空,对于我们的例子,如下代码:

    1 if (name != null && name.equals("Jackson")){}

      通过判断name是否为空,若非空再判断name是否等于Jackson。通过这样的方式可以解决空指针异常的问题。

      但是两种方案都有一定的缺点,对于第一种方案,String和集合类型的Null对象很好确认,就是空字符串和空集合。但是对于一些特殊的对象,创建Null对象需要更多的步骤,更多的设计。总之就是两个字,麻烦。

      对于第二种方案,这个也是我们最常用的。但是这个方案有一个问题,就是经常会忘记判空。对于一个方法other.method(a, b),我们常常不会忘记对a和b进行判空,而对方法的返回值却经常忘记判空。而这个空指针异常是在运行时才会被发现,如果空指针的情况十分的罕见,那么很可能很长一段时间都不会发现这个异常。我常常碰到的一种情况是当数据库中存在脏数据的时候,正常的数据是不应该存在null的,但是即使是生产环境也很有可能混入一两个脏数据,很可能这罕见的脏数据导致程序报错。可能这个时候再去修复bug,代价比开发阶段高很多。

      为了优雅地处理null的情况,可以使用Java8的新特性Optional。API不说了,直接上代码

     1 public class Person {
     2 
     3     private String name;
     4 
     5     public Person() {
     6     }
     7 
     8     public Person(String name) {
     9         this.name = name;
    10     }
    11 
    12     public Optional<String> getName() {
    13         return Optional.ofNullable(name);
    14     }
    15 
    16     public static void main(String[] args) {
    17         Person person = new Person();
    18 
    19         Optional<String> optionalName = person.getName();
    20         if (optionalName.isPresent()) {
    21             String name = optionalName.get();
    22             System.out.println("My name is :" + name);
    23         } else {
    24             System.out.println("Who am I?");
    25         }
    26     }
    27 }

      在getName里,我们由原来直接返回name,改成返回Optional<String>。通过Optional.ofNullable(T)静态方法,可以创建一个Optional对象。如果传入的对象是null,那么isPresent返回false,否则返回true。在上诉代码中,Person的name没有设置,optionalName.isPresent()返回的是false,所以打印出的应该是Who am I?

      从代码上看,这个和第二种方案,对对象判空的方法没有区别,都是先判断是否存在,然后再对对象进行操作。因为我们没法直接获取所需的对象,而是获得Optional对象,需要从Optional中获取我们需要的对象,因为不判空取不到所需对象,所以我们就不会忘了判空这步操作了。

  • 相关阅读:
    [bzoj1008](HNOI2008)越狱(矩阵快速幂加速递推)
    [BZOJ1007](HNOI2008)水平可见直线(半平面交习题)
    [bzoj1006](HNOI2008)神奇的国度(弦图最小染色)【太难不会】
    [BZOJ1005](HNOI 2008)明明的烦恼
    unity3d环境安装指南: Unity 4.5.5 + Visual Studio 2010
    再议Unity 3D
    Android系统简介(中):系统架构
    Android系统简介(上):历史渊源
    Spread 之自定义对角线cellType源码: DiagonalCellType
    通信行业OSS支撑系统软件研发思考
  • 原文地址:https://www.cnblogs.com/zsh-blogs/p/11275923.html
Copyright © 2020-2023  润新知