Java小技巧:Java 8 Optional 类的使用

1. 问题和需求

先来看一个简单的类:

class Person{
    private String name;

    public String getName() {
        return name;
    }

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

当我们调用getName来获取name时,可能值为空,那么就会出现下面这样的代码:

Person p = getPerson();
if(p.getName() != null){
    //do something...
}
//或者
if(Person.isNameNotEmpty(p)){
    //do something...
}

这里会有两个问题:

  1. 代码稍微多了且不紧凑;
  2. 只看方法签名无法直接判断是否为空,无法表示 String|null 这样的类型;

而我们的需求是:

  1. 优雅地处理空判断;
  2. 在方法签名上就能看出这个方法的返回值可能存在可能不存在。

2. Optional类介绍

java.util.Optional类是 Java 8 引入的工具类,表示“可选的”意思,作为单一对象的包装容器,提供一系列方法来优雅的处理空判断和后续操作。

首先是创建Optional对象:

Optional<T> opt = Optional.empty();           //空 Optional
Optional<T> opt1 = Optional.of(value);         //不为空的 Optional,如果 value 为 null,会抛出异常
Optional<T> opt2 = Optional.ofNullable(value); //可能为空也可能不为空的 Optional

判断是否为空:

opt.isEmpty();
opt.isPresent();

判空并执行相应动作:

opt.ifPresent(s -> { //if...
    //存在的情况,do something...
});

opt.ifPresentOrElse(s -> { //if...else...
    //存在的情况,do something...
}, () -> {
    //不存在的情况,do something...
});

从Optional中取值:

opt.get();                              //取出值或抛出异常
opt.orElse(defValue);                   //取出值或者为默认值
opt.orElseGet(() -> getDefXXXValue());  //取出值或者获取默认值
opt.orElseThrow();                      //取出值或抛出异常,同 get
opt.orElseThrow(() -> new IllegalStateException("xxx"));//取出值或抛出指定

链式调用:

int value = opt
                .filter(s -> s.length() > 0)                    //过滤长度为 0 的字符串
                .or(() -> Optional.of("empty"))                 //如果为空就换成"empty"
                .map(s -> "str:" + s)                           //添加前缀
                .flatMap(s -> {                                 //转成整数
                    try{
                        return Optional.of(Integer.parseInt(s));
                    } catch (NumberFormatException e) {
                        return Optional.empty();
                    }
                })
                .orElse(0);                                     //获取值或默认值

转成流对象:

Stream<T> stream = opt.stream();
//然后就可以用Stream的API来处理Optional里的值了。

最后,我们可以用Optional来修改最上面的例子:

class Person {
    private String name;

    public String getName() {
        return name;
    }

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

    //关心是否为空的就可以用这个方法来放心优雅使用了
    public Optional<String> optName() { 
        return Optional.ofNullable(name);
    }
}

你可能感兴趣的:(Java)