美文网首页
【Java】Java8新特性(一)Optional类

【Java】Java8新特性(一)Optional类

作者: 如雨随行2020 | 来源:发表于2022-01-30 00:13 被阅读0次

对于NPE,Java8对于null判定提供了一种更加优雅的实现,Optional类。
比如我们要返回一个字符串的长度
java8以前:

if(null == str) {
    return 0;
}
return str.length();

使用Optional

        return Optional.ofNullable(str).map(String::length).orElse(0);

Optional的代码相对更加简洁,当代码量较大时,我们很容易忘记进行null判定,但是使用Optional类可以很大的避免这类问题

一、基本使用

1.1 Optional对象的创建

  • 创建空对象
Optional<String> optStr = Optional.empty();
  • 创建对象(不允许为空)
Optional<String> optStr = Optional.of(str);  // 当str为null的时候,将抛出NullPointException
  • 创建对象(允许为空)
Optional<String> optStr = Optional.ofNullable(str);  // 如果str是null,则创建一个空对象

1.2 流式数据处理

Optional类提供了两个基本的流式处理:映射和过滤
我们先创建一个User类

public class User {
    private long id;
    private String name;
    private int age;
    private Optional<Long> phone;
    private Optional<String> email;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 省略getter和setter
}

这里phone和email我们使用Optional类定义

  • 映射:map与flatMap
    获取用户名字
        User user = new User("jack", 23);
        String name = Optional.ofNullable(user).map(User::getName).orElse("no name");

如果user为null或者user.getName()为null,返回no name,
只有user与user的name同时不为null时,结果才是有效的。
获取用户手机时,map之后返回的是Optional,我们把这种称为Optional嵌套,我们必须再map一次才能拿到想要的结果

long phone = Optional.ofNullable(user).map(User::getPhone).map(Optional::get).orElse(-1L);

其实我们有一种更好的方式

phone = Optional.ofNullable(user).flatMap(User::getPhone).orElse(-1L);

<font color="red">这种方式有问题,如果user不为null,但是phone为null时,报NPE</font>

  • 过滤:filter
    假若我们希望筛选18周岁以上的成年人
Optional.ofNullable(user).filter(u -> u.getAge() >= 18).ifPresent(u -> System.out.println("Adult:" + u));

如果user年龄超过18,则打印user

1.3 默认行为

  • get()

get方法用于获取变量的值,当变量不存在时抛NoSuchElementExcepton

  • orElse(T other)

当Optional的变量不满足给定条件时,执行orElse

  • orElseGet(Supplier<? extends X> expectionSupplier)

如果条件不成立时需要执行相对复杂的逻辑而不是简单的返回操作,则可以使用orElseGet实现

        String name = Optional.ofNullable(user).map(User::getName).orElseGet(() -> {
            System.out.println("这个用户没有名字吗?");
            return "no name";
        });

当user==null或者user.getName() == null时,会运行orElseGet参数的方法。

  • orElseThrow(Supplier<? extends X> expectionSupplier)
        name = Optional.ofNullable(user).map(User::getName).orElseThrow(Exception::new);

或者

        name = Optional.ofNullable(user).map(User::getName).orElseThrow(() -> {
            System.out.println("这个用户没有名字,我抛异常了");
            return new Exception();
        });
  • ifPresent(Consumer<? super T>)

二、注意事项

Optional是一个final类且未实现任何接口(比如Serializable),所以当我们在利用该类包装定义类的属性的时候,如果我们定义的类有序列化的需求,那么因为 Optional 没有实现 Serializable 接口,这个时候执行序列化操作就会有问题:

public class User implements Serializable {
    private long id;
    private String name;
    private int age;
    private Optional<Long> phone;  // 不能序列化
    private Optional<String> email;  // 不能序列化
}

不过我们可以采用如下替换策略 Optinal:

private long phone;

public Optional<Long> getPhone() {
    return Optional.ofNullable(this.phone);
}

看来 Optional 类在设计的时候就没有考虑将它作为类的字段使用。

相关文章

网友评论

      本文标题:【Java】Java8新特性(一)Optional类

      本文链接:https://www.haomeiwen.com/subject/mmeraltx.html