java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > JDK8 Optional类

JDK8新出Optional类的方法探索与思考分析

作者:彼岸花开可奈何

这篇文章主要为大家介绍了JDK8新出Optional类的发方法示例探索与思考分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

所有的 Java 程序员基本都会遇到 NullPointerException 异常,一般处理这个问题可能不会是很难,但是有时去排查到底是哪引起的会耗费很长时间很是麻烦。最近了解到 JDK1.8 新增加了一个 Optional 类可以避免一些 NullPointerException 异常,下面让我们一起去了解一下它吧。

基于值的类(Value-based Classes)

有些类,如 java.util.Optional 和 java.time.LocalDateTime,是基于值的。基于值的类的实例:

如果程序试图区分对基于值的类的相等值的两个引用,无论是直接通过引用相等,还是间接通过调用同步、身份哈希、序列化或任何其他身份敏感机制,都可能产生不可预测的结果。在基于值的类的实例上使用这种对身份敏感的操作可能会产生不可预测的影响,应该避免。

简单地说,基于值的类的实例是最终的,不可变的,并且这些实例没有适当的状态和标识,因此某些操作是特定于标识的,因此不应使用。

一、Optional中的基本方法

Optional 类位于 java.util 包下,它是一个容器对象,可能包含也可能不包含非空值。

这是一个基于值的类;在Optional实例上使用身份敏感操作(包括引用相等(==)、身份哈希码或同步)可能会产生不可预测的结果,应该避免。

1、创建方法

empty()

返回一个空的 Optional 实例

public class Main {
    public static void main(String[] args) {
        System.out.println(Optional);
    }
}
// 输出
Optional.empty

注意:不要通过与Option.empty()返回的实例进行==比较来避免测试对象是否为空,因为不能保证它是单例的。

of(T value)

返回一个带值的 Optional,如果 value 是 null 会抛出 NullPointerException 异常

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.of("emanjusaka");
        System.out.println(emanjusaka);
    }
// 输出
Optional[emanjusaka]

ofNullable(T value)

如果非空,返回描述指定值的 Optional,否则返回空 Optional。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.ofNullable("emanjusaka");
        System.out.println(emanjusaka);

        Optional<String> empty = Optional.ofNullable(null);
        System.out.println(empty);
    }
// 输出
Optional[emanjusaka]
Optional.empty

2、判断方法

isPresent()

如果存在值则返回 true,否则返回 false。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.ofNullable("emanjusaka");
        System.out.println(emanjusaka);
        System.out.println(emanjusaka.isPresent());
        Optional<String> empty = Optional.ofNullable(null);
        System.out.println(empty);
        System.out.println(empty.isPresent());
    }
//输出
Optional[emanjusaka]
true
Optional.empty
false

​ifPresent(Consumer<? super T> consumer)​​

如果存在值,则使用该值调用指定的消费者,否则什么都不做。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.of("emanjusaka");
        Consumer<String> consumer = s -> {
            s = "hello " + s;
            System.out.println(s);
        };
        System.out.println(emanjusaka);
        emanjusaka.ifPresent(consumer);
    }
// 输出
Optional[emanjusaka]
hello emanjusaka

一般用于判断 Optional 是否为空,并在不为空的情况下执行相应的操作。

3、获取方法

get()

如果这个 Optional 中存在一个值,则返回该值,否则抛出 NoSuchElementException。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.ofNullable("emanjusaka");
        System.out.println(emanjusaka);
        System.out.println(emanjusaka.get());
        Optional<String> empty = Optional.ofNullable(null);
        System.out.println(empty);
        System.out.println(empty.get());
    }
// 输出
Optional[emanjusaka]
emanjusaka
Optional.empty
Exception in thread "main" java.util.NoSuchElementException: No value present
    at java.util.Optional.get(Optional.java:135)
    at org.example.Main.main(Main.java:13)

filter(Predicate<? super T> predicate)

如果存在一个值,并且该值与给定的过滤条件匹配,则返回一个描述该值的 Optional,否则返回一个空的 Optional。

public static void main(String[] args) {
        Optional<String> emanjusaka = Optional.of("emanjusaka");
        System.out.println(emanjusaka);
        System.out.println(emanjusaka.filter(s -> {
            return "emanjusaka".equals(s);
        }));
        System.out.println(emanjusaka.filter(s -> false));
    }
// 输出
Optional[emanjusaka]
Optional[emanjusaka]
Optional.empty

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

如果存在值,则将提供的映射函数应用于该值,如果结果为非 null,则返回一个描述结果的 Optional。否则返回空的 Optional。

public static void main(String[] args) {
        User user = new User();
        user.setName("emanjusaka");
        Optional<User> optional = Optional.of(user);
        System.out.println(optional);
        System.out.println(optional.map(User::getName));
        User userEmpty = new User();
        Optional<User> optionalEmpty = Optional.of(userEmpty);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.map(User::getName));
    }
    private static class User {
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
// 输出
Optional[org.example.Main$User@2503dbd3]
Optional[emanjusaka]
Optional[org.example.Main$User@6d03e736]
Optional.empty

flatMap(Function<? super T, Optionalu> mapper)

如果存在值,请将提供的 Optional 方位映射函数应用于该值,返回该结果,否则返回空的 Optional。此方法类似于map(Function),但提供的 mapper 的结果已经是 Optional,并且如果调用,flatMap 不会用额外的 Optional 包装它。

public static void main(String[] args) {
        User user = new User();
        user.setName("emanjusaka");
        user.setAge(Optional.of(35));
        Optional<User> optional = Optional.of(user);
        System.out.println(optional);
        System.out.println(optional.map(User::getAge));
        System.out.println(optional.flatMap(User::getAge));
    }
    private static class User {
        private String name;
        private Optional<Integer> age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Optional<Integer> getAge() {
            return age;
        }
        public void setAge(Optional<Integer> age) {
            this.age = age;
        }
    }
// 输出
Optional[org.example.Main$User@2503dbd3]
Optional[Optional[35]]
Optional[35]

这个例子中体现出了 map 和 flatMap 方法的区别,map 方法会在返回时用 Optional 进行包装而 flatMap 方法不会再进行额外的包装。

orElse(T other)

如果存在这个值则返回这个值,否则返回传入的值 other

public static void main(String[] args) {
        Optional<String> optional = Optional.of("emanjusaka");
        System.out.println(optional);
        System.out.println(optional.orElse(null));
        Optional<String> optionalEmpty = Optional.ofNullable(null);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.orElse("empty"));
    }
// 输出
Optional[emanjusaka]
emanjusaka
Optional.empty
empty

orElseGet(Supplier<? extends T> other)

如果存在这个值则返回这个值,否则调用 other 并返回该调用的结果。

public static void main(String[] args) {
        Optional<String> optional = Optional.of("emanjusaka");
        System.out.println(optional);
        System.out.println(optional.orElseGet(() -> "hello emanjusaka"));
        Optional<String> optionalEmpty = Optional.ofNullable(null);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.orElseGet(() -> "hello emanjusaka"));
    }
// 输出
Optional[emanjusaka]
emanjusaka
Optional.empty
hello emanjusaka

orElseThrow(Supplier? extends X exceptionSupplier)

返回包含的值(如果存在),否则抛出由所提供创建的异常。

public static void main(String[] args) {
        Optional<String> optionalEmpty = Optional.ofNullable(null);
        System.out.println(optionalEmpty);
        System.out.println(optionalEmpty.orElseThrow(ArithmeticException::new));
    }
// 输出
Optional.empty
Exception in thread "main" java.lang.ArithmeticException
    at java.util.Optional.orElseThrow(Optional.java:290)
    at org.example.Main.main(Main.java:9)

二、Optional 中方法的区别

1、map 和 flatMap 方法的区别

2、orElse 和 orElseGet 方法的区别

如果是传值可以选用 orElse(),如果传入的是方法选用orElseGet()​​。

三、总结

在使用 Optional 时我觉得应该尽量避免一些情况:

总之,如果发现自己编写的方法不能总是返回值,并且认为该方法的用户在每次调用时考虑这种可能性很重要,那么或许应该返回一个 Optional 的方法。但是,应该意识到,返回 Optional 会带来实际的性能后果;对于性能关键的方法,最好返回 null 或抛出异常。最后,除了作为返回值之外,不应该在任何其他地方中使用 Optional。

使用 Optional 时要注意,我认为它并不能完全避免空指针。如果这个值是 null ,不做额外的判断,直接使用还是会有空指针的问题。使用 Optional 的好处是它可以帮助我们简化判空的操作,简洁我们的代码。用了 Optional 最后拿结果的时候还是要小心的,盲目 get 一样会抛错。

参考文献

《Effective Java》jdk11的文档

以上就是JDK8新出Optional类的方法探索与思考分析的详细内容,更多关于JDK8 Optional类的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文