温故而知新:Java 8 之 Optional

Java 11 已经发布很久了,而很多企业还在用很老的 Java 版本,这年头,再保守的企业也应该用上 Java 8 了。我们不妨回顾一下 Java 8 的新(现已是老)特性。

主要 API

java.util.Optional 的那些方法(method)倒是没啥可讲的,看看文档就行了。这里简要列举一下:

构造:

static <T> Optional<T> empty()
static <T> Optional<T> of(T value)
static <T> Optional<T> ofNullable(T value)

Optional 的构造方法都是私有的,提供 3 个静态方法来生成 Optional 对象。其中,empty 构造一个内部不含值的 Optional 对象,of 不接受 nullofNullable 可以接受 null

其他方法:

T get()
boolean isPresent()
void ifPresent(Consumer<? super T> consumer)
Optional<T> filter(Predicate<? super T> predicate)
<U> Optional<U> map(Function<? super T, ? extends U> mapper)
<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
T orElse(T other)
T orElseGet(Supplier<? extends T> other)
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

作用分别如下:

T get()

获取里面的值,若不存在,引发 NoSuchElementException

boolean isPresent()

检查里面是否有值。

void ifPresent(Consumer<? super T> consumer)

如果里面有值,则对那个值做一些处理(消费它)。

Optional<T> filter(Predicate<? super T> predicate)

用条件 predicate 进行过滤,条件满足则返回本身,否则返回一个不含值的 Optional<T>

<U> Optional<U> map(Function<? super T, ? extends U> mapper)
<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

二者大同小异,都是对里面的值进行某种操作,不同的是,flatMap 要求返回值是 Optional<U>

T orElse(T other)
T orElseGet(Supplier<? extends T> other)
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

这三个方法都是获取值,不同点在于无值时三者的行为:orElse 提供一个默认值 otherorElseGet 提供由一个函数返回的值,orElseThrow 引发一个异常。

正着

我们最容易想到的用法当然是 isPresent

Optional<String> os = Optional.ofNullable(s);
if (os.isPresent()) {
    // 一些代码
}

但这么做没啥意义,还不如与 null 作比较直观。

Optional 也不应出现在函数的参数上,因为调用者不该有这样的心智负担。

就像这篇文章

http://www.importnew.com/22060.html

所言,我们需要的是除了 isPresentget 之外的其他方法。

例如,我们在程序中要读取 FLUTE_DEBUG 环境变量,如果它存在,且在不区分大小写的情况下属于 "true""on""1",则认为程序处于调试模式下,否则认为处于生产模式下。

public static boolean inDebugMode() {
    return Optional.ofNullable(System.getenv("FLUTE_DEBUG"))
            .map(String::toLowerCase)
            .map(s -> "true".equals(s) || "on".equals(s) || "1".equals(s))
            .orElse(false);
}

再例如,用来实现函数的默认参数:

class MqttClientConfig {
    // 各个属性省略
}

class MqttClient {
    private MqttClient() {
    }

    private static MqttClientConfig getDefaultConfig() {
        // 将所有的属性设为默认
        // 此处从略
        return new MqttClientConfig();
    }

    public static MqttClient create(MqttClientConfig config) {
        // 如果 config 为 null
        // 则一切按照默认
        MqttClientConfig theConfig = Optional.ofNullable(config).orElseGet(MqttClient::getDefaultConfig);

        // ......
    }
}

上面的代码示意了一个 MQTT 客户端创建的过程。当然,只有一个参数的方法,用这样的方式不如加一个重载,当参数多的时候,Optional 的便利才得以体现。

转载于:https://my.oschina.net/jthmath/blog/3050442

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值