什么是Optional


为什么需要Optional?
日常代码中,如果程序出现空指针的话,我们一般需要进行多个if判断或try-catch来保证代码不会出现空指针异常,但这样就会导致代码可读性下降,而Optional提供了简洁的语法解决空指针。

通过简单示例的对比就可以了解:

  • 没有使用Optional
public class OptionalTests {  
  
    public static User getUserByIdFromDB() {  
        // 当前 ID 的用户不存在  
        return null;  
    }  
  
    @Test  
    public void test01() {  
        User user = getUserByIdFromDB();  
        // 普通处理 空指针  
        if (user != null) System.out.println(user.getName());  
    }  
  
    @Test  
    public void test02() {  
        User user = null;  
//        User user = new User();  
//        user.setName("zxb");  
        Optional.ofNullable(user).ifPresent(System.out::println);  
    }
  
    class User {  
        private String name;  
  
        public String getName() {  
            return name;  
        }  
  
        public void setName(String name) {  
            this.name = name;  
        }  
    }
 
}
  • 使用Optional
@Test  
public void test02() {  
    User user = null;  
      User user = new User();  
      user.setName("zxb");  
    Optional.ofNullable(user).ifPresent(System.out::println);  
}

class User {  
    private String name;  

    public String getName() {  
        return name;  
    }  

    public void setName(String name) {  
        this.name = name;  
    }  
}

通过示例可以看出,Optional是一个工具类,可以链式的解决空指针等问题,并且Stream的方法也有很多会返回Optional

创建Optional对象


  1. 可以使用静态方法 empty() 创建一个空的 Optional 对象
Optional<String> empty = Optional.empty();  
System.out.println(empty); // Optional.empty
  1. 可以使用静态方法 of() 创建一个非空的 Optional 对象
Optional<String> opt = Optional.of("zxb");  
System.out.println(opt); // Optional[zxb]

但如果是 null,依然还是会报空指针异常

  1. 可以使用静态方法 ofNullable() 创建一个即可空又可非空的 Optional 对象
String name = null;  
Optional<String> optOrNull = Optional.ofNullable(name);  
System.out.println(optOrNull); // Optional.empty

判断值是否存在


可以通过 isPresent() 判断一个 Optional 对象是否存在,如果存在,该方法返回 true——取代了 obj != null

Optional<String> opt = Optional.of("zxb");  
System.out.println(opt.isPresent()); // true  
  
Optional<String> optOrNull = Optional.ofNullable(null);  
System.out.println(optOrNull.isPresent()); // false

非空表达式


Optional 类有一个非常现代化的方法——ifPresent(),允许我们使用函数式编程的方式执行一些代码,因此,将它称为非空表达式。

ifPresent() 可以使用 lambda:

Optional<String> optOrNull = Optional.ofNullable(null);  
if (optOrNull.isPresent()) System.out.println(optOrNull.get().length());  
  
Optional<String> opt = Optional.of("zxb");  
opt.ifPresent(str -> System.out.println(str.length())); // 3

Java 9 后还可以通过方法 ifPresentOrElse(action, emptyAction) 执行两种结果,非空时执行 action,空时执行 emptyAction。

Optional<String> opt = Optional.of("沉默王二");
opt.ifPresentOrElse(str -> System.out.println(str.length()), () -> System.out.println("为空"));

设置(获取)默认值


当创建(获取)Optional 对象的时候,需要默认值,可以使用 orElse()orElseGet()
orElse() 方法用于返回包裹在 Optional 对象中的值,如果该值不为null,则返回;否则返回默认值。

String nullName = null;
String name = Optional.ofNullable(nullName).orElse("zxb");
System.out.println(name); // zxb

orElseGet() 方法与 orElse() 方法类似,但参数类型不同。

String nullName = null;
String name = Optional.ofNullable(nullName).orElseGet(() -> "zxb");
System.out.println(name); // zxb

获取值


get() 方法才是正常获取 Optional 对象值的方法,但尽量使用 orElseGet() 可以避免空指针。

String name = null;
Optional<String> optOrNull = Optional.ofNullable(name);
System.out.println(optOrNull.get()); // NoSuchElementException