JAVA 8 Optional类介绍及其源码

什么是Optional对象

Java 8中所谓的Optional对象,即一个容器对象,该对象可以包含一个null或非null值。如果该值不为null,则调用isPresent()方法将返回true,且调用get()方法会返回该值。

另外,该对象还有其它方法:

如可以使用orElse()方法给Optional对象设定默认值(当值为null时,会使用默认值);

使用ifPresent()方法来执行一段代码(当值不为null时,执行代码段)。

Optional主要被用于Java 8的Stream中,简单举个例子:

JAVA 8 Optional类介绍及其源码
package optional;

import java.util.Optional;
import java.util.stream.Stream;

public class Snippet
{
    public static void main(String[] args)
    {
        Stream<String> names = Stream.of("Lamurudu", "Okanbi", "Oduduwa");
        
        Optional<String> startswl = names.filter(name -> name.startsWith("L")).findFirst();
        
        //判断是否不为null
        if(startswl.isPresent()){
            System.out.println(startswl.get());
        }
        
        //if值为null:打印“null”;if值不为null:打印原值
        System.out.println(startswl.orElse("null"));

        //if值不为null,执行Lambda表达式
        startswl.ifPresent(name -> {
            String s = name.toUpperCase();
            System.out.println(s);
        });
    }
}
JAVA 8 Optional类介绍及其源码

使用Optional对象的好处

减少NullPointerException异常

写出更加优雅的代码

源码及示例

Optional类的属性和方法如下:

 JAVA 8 Optional类介绍及其源码

我们一个个看,先看两个成员属性;

成员属性

如下,一个是EMPTY常量,即存放空值的Optional对象,另一个是value,即被存放的值,可为null或非null值;

JAVA 8 Optional类介绍及其源码
    /**
     * Common instance for {@code empty()}.
     */
    private static final Optional<?> EMPTY = new Optional<>();

    /**
     * If non-null, the value; if null, indicates no value is present
     */
    private final T value;
JAVA 8 Optional类介绍及其源码

构造方法

两个构造方法,注意都是私有的

1、创建一个包含空值的Optional对象;

2、创建一个非空值的Optional对象;

    private Optional() {
        this.value = null;
    }
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

empty()方法

这个方法很简单,作用是返回一个Optional实例,里面存放的value是null,源码如下:

    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

of(T value)方法

很简单,就是返回一个包含非空值的Optional对象

    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

ofNullable(T value)方法

 很简单,返回一个可以包含空值的Optional对象

    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

get()方法

 得到Optional对象里的值,如果值为null,则抛出NoSuchElementException异常

    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

isPresent()方法

很简单,判断值是否不为null

    public boolean isPresent() {
        return value != null;
    }

ifPresent(Consumer<? super T> consumer)方法

 当值不为null时,执行consumer

    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

举个例子,ifPresent方法执行Lambda表达式,将值转换为大写并打印:

JAVA 8 Optional类介绍及其源码
package optional;

import java.util.Optional;

public class Snippet
{
    public static void main(String[] args)
    {
        Optional<String> test = Optional.ofNullable("abcDef");
        
        //值不为null,执行Lambda表达式,
        test.ifPresent(name -> {
            String s = name.toUpperCase();
            System.out.println(s);
        });
        //打印ABCDEF
    }
}
JAVA 8 Optional类介绍及其源码

filter(Predicate<? super T> predicate)方法

看方法名就知道,该方法是过滤方法,过滤符合条件的Optional对象,这里的条件用Lambda表达式来定义,

如果入参predicate对象为null将抛NullPointerException异常,

如果Optional对象的值为null,将直接返回该Optional对象,

如果Optional对象的值符合限定条件(Lambda表达式来定义),返回该值,否则返回空的Optional对象

源码如下:

JAVA 8 Optional类介绍及其源码
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }
JAVA 8 Optional类介绍及其源码

使用示例:

JAVA 8 Optional类介绍及其源码
package optional;

import java.util.Optional;

public class Snippet
{
    public static void main(String[] args)
    {
        Optional<String> test = Optional.ofNullable("abcD");
        
        //过滤值的长度小于3的Optional对象
        Optional<String> less3 = test.filter((value) -> value.length() < 3);
        //打印结果
        System.out.println(less3.orElse("不符合条件,不打印值!"));
    }
}
JAVA 8 Optional类介绍及其源码

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

 前面的filter方法主要用于过滤,一般不会修改Optional里面的值,map方法则一般用于修改该值,并返回修改后的Optional对象

如果入参mapper对象为null将抛NullPointerException异常,

如果Optional对象的值为null,将直接返回该Optional对象,

最后,执行传入的lambda表达式,并返回经lambda表达式操作后的Optional对象

JAVA 8 Optional类介绍及其源码
    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
JAVA 8 Optional类介绍及其源码

使用示例:

JAVA 8 Optional类介绍及其源码
package optional;

import java.util.Optional;

public class Snippet
{
    public static void main(String[] args)
    {
        Optional<String> test = Optional.ofNullable("abcD");
        
        //将值修改为大写
        Optional<String> less3 = test.map((value) -> value.toUpperCase());
        //打印结果 ABCD
        System.out.println(less3.orElse("值为null,不打印!"));
    }
}
JAVA 8 Optional类介绍及其源码

flatMap(Function<? super T, Optional<U>> mapper)方法

flatMap方法与map方法基本一致,唯一的区别是,

如果使用flatMap方法,需要自己在Lambda表达式里将返回值转换成Optional对象,

而使用map方法则不需要这个步骤,因为map方法的源码里已经调用了Optional.ofNullable方法;

源码:

JAVA 8 Optional类介绍及其源码
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }
JAVA 8 Optional类介绍及其源码

使用示例:

JAVA 8 Optional类介绍及其源码
package optional;

import java.util.Optional;

public class Snippet
{
    public static void main(String[] args)
    {
        Optional<String> test = Optional.ofNullable("abcD");
        
        //使用flatMap,将值修改为大写
        Optional<String> less3 = test.flatMap((value) -> Optional.ofNullable(value.toUpperCase()));
        //使用map,将值修改为大写
        //Optional<String> less3 = test.map((value) -> value.toUpperCase());
        
        //打印结果 ABCD
        System.out.println(less3.orElse("值为null,不打印!"));
    }
}
JAVA 8 Optional类介绍及其源码

orElse(T other)方法

很简单,当值为null时返回传入的值,否则返回原值;

源码:

    public T orElse(T other) {
        return value != null ? value : other;
    }

orElseGet(Supplier<? extends T> other)方法

功能与orElse(T other)类似,不过该方法可选值的获取不是通过参数直接获取,而是通过调用传入的Lambda表达式获取

源码:

    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

使用示例:

JAVA 8 Optional类介绍及其源码
package optional;

import java.util.Optional;

public class Snippet
{
    public static void main(String[] args)
    {
        Optional<String> test = Optional.ofNullable(null);

        System.out.println(test.orElseGet(() -> "hello"));
        //将打印hello
    }
}
JAVA 8 Optional类介绍及其源码

orElseThrow(Supplier<? extends X> exceptionSupplier)方法

当遇到值为null时,根据传入的Lambda表达式跑出指定异常

源码

JAVA 8 Optional类介绍及其源码
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }
JAVA 8 Optional类介绍及其源码

使用示例:

JAVA 8 Optional类介绍及其源码
package optional;

import java.util.Optional;

public class Snippet
{
    public static void main(String[] args)
    {
        Optional<String> test = Optional.ofNullable(null);

        //这里的Lambda表达式为构造方法引用
        System.out.println(test.orElseThrow(NullPointerException::new));
        //将打印hello
    }
}
JAVA 8 Optional类介绍及其源码
本文转自风一样的码农博客园博客,原文链接:http://www.cnblogs.com/chenpi/p/5923829.html,如需转载请自行联系原作者
上一篇:常见Java面试题 BIO、NIO、AIO 有什么区别?


下一篇:泛函编程(22)-泛函数据类型-Monoid In Action