美文网首页
Java8特性学习笔记(三) Optional

Java8特性学习笔记(三) Optional

作者: 简单一点点 | 来源:发表于2021-12-24 17:10 被阅读0次

参考:

简介

Optional 是 Java8 提供的为了解决 null 安全问题的一个 API。善用 Optional 可以使我们代码中很多繁琐的设计变得十分优雅。

示例

为了方便,我们先定义一个简单的实体类 Book。

public class Book {
    
    private String name;
    private float price;

    public Book(String name, float price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

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

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

然后看个例子,传统写法如下:

public static String getName(Book book) {
    if (book == null || book.getName() == null)
        return "Unknown";
    return book.getName();
}

使用 Optional 改为链式调用如下:

public static String getName(Book book) {
    return Optional.ofNullable(book)
            .map(user->user.getName())
            .orElse("Unknown");
}

不推荐的写法如下,这其实只是用 isPresent 方法来替代 u==null

public static String getName(Book book) {
    Optional<Book> myBook = Optional.ofNullable(book);
    if (!myBook.isPresent())
        return "Unknown";
    return myBook.get().getName();
}

构造方法

Java 提供三个静态方法来构造一个Optional:

  • Optional.of(T value),该方法通过一个非 null 的 value 来构造一个 Optional,返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException。
Optional<String> optStr1 = Optional.of("optional");
  • Optional.ofNullable(T value),该方法和 of 方法的区别在于,传入的参数可以为 null , 但是前面 javadoc 不是说 Optional 只能包含非 null 值吗?原来该方法会判断传入的参数是否为 null,如果为 null 的话,返回的就是 Optional.empty()。
Optional<String> optStr2 = Optional.ofNullable(null);
  • Optional.empty(),该方法用来构造一个空的 Optional,即该 Optional 中不包含值,其实底层实现还是 如果 Optional 中的 value 为 null 则该 Optional 为不包含值的状态,然后在 API 层面将 Optional 表现的不能包含 null 值,使得 Optional 只存在 包含值 和 不包含值 两种状态。
Optional<String> optStr = Optional.empty();

API方法

介绍一些经常使用的方法。

get

get()方法主要用于返回包装对象的实际值,但是如果包装对象值为null,会抛出NoSuchElementException异常。

示例:

String name = Optional.ofNullable(book).get().getName(); // book 不能为空

方法源码:

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

isPresent

isPresent()方法用于判断包装对象的值是否非空。

使用示例:

System.out.println(Optional.ofNullable(book).isPresent()); 

方法源码:

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

ifPresent

ifPresent()方法接受一个Consumer对象(消费函数),如果包装对象的值非空,运行Consumer对象的accept()方法。

示例:

public static void printName(Book book) {
    Optional.ofNullable(book).ifPresent(b ->  System.out.println("The Book name is : " + b.getName()));
}

方法源码:

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

filter

filter() 方法接受参数为 Predicate 对象,用于对 Optional 对象进行过滤,如果符合 Predicate 的条件,返回 Optional 对象本身,否则返回一个空的 Optional 对象。举例如下:

示例:

public static void filterPrice(Book book) {
    Optional.ofNullable(book).filter( b -> b.getPrice() > 10.0).ifPresent(b ->  System.out.println("The book price is more than 10.0."));
}

方法源码:

public Optional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    if (!isPresent())
        return this;
    else
        return predicate.test(value) ? this : empty();
}

map

map() 方法的参数为 Function(函数式接口)对象,map()方法将 Optional 中的包装对象用 Function 函数进行运算,并包装成新的 Optional 对象(包装对象的类型可能改变)。

public static Optional<Float> getPrice(Book book) {
    return Optional.ofNullable(book).map(u -> u.getPrice());
}

方法源码:

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));
    }
}

flatMap

跟map()方法不同的是,入参Function函数的返回值类型为 Optional<U> 类型,而不是 U 类型,这样 flatMap() 能将一个二维的Optional对象映射成一个一维的对象。将上例进行faltMap()改写如下:

public static Optional<Float> getPrice(Book book) {
    return Optional.ofNullable(book).flatMap(b -> Optional.ofNullable(b.getPrice()));
}

方法源码:

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));
    }
}

orElse

orElse()方法功能比较简单,即如果包装对象值非空,返回包装对象值,否则返回入参other的值(默认值)。

示例:

public static String getName(Book book) {
    return Optional.ofNullable(book)
            .map(user->user.getName())
            .orElse("Unknown");
}

方法源码:

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

orElseGet

orElseGet()方法与orElse()方法类似,区别在于orElseGet()方法的入参为一个Supplier对象,用Supplier对象的get()方法的返回值作为默认值。

示例:

public static String getName(Book book) {
    return Optional.ofNullable(book)
            .map(user->user.getName())
            .orElseGet(() -> "Unkown");
}

方法源码:

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

orElseThrow

orElseThrow()方法其实与orElseGet()方法非常相似了,入参都是Supplier对象,只不过orElseThrow()的Supplier对象必须返回一个Throwable异常,并在orElseThrow()中将异常抛出。

示例:

public static String getName(Book book) {
    return Optional.ofNullable(book)
            .map(user->user.getName())
            .orElseThrow(() -> new RuntimeException("Unkown"));
}

方法源码:

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

相关文章

  • Java8特性学习笔记(三) Optional

    参考: https://www.jianshu.com/p/d81a5f7c9c4e[https://www.ji...

  • JAVA8新特性-Optional类解决NPE问题

    ** JAVA8新特性-Optional类解决NPE问题** API介绍 1、Optional(T value),...

  • Optional 类

    Optional 类 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! 到目前为止,臭名昭著的...

  • Optional源码分析(未完)

    Optional源码分析(未完) Optional 类是Java8的新特性,Optional是一个可以为null的...

  • java8 - optional

    optional 是java8的新特性,The purpose of the class is to provid...

  • JAVA8- Optional-用法浅析

    JAVA8- Optional-用法浅析 简介 java8新引入optional特性,官方说法是更优雅的处理空指针...

  • Java8中的lambda表达式

    lambda表达式是Java8中最重要的特性之一,也是Stream,Optional等特性的基础。尽管lambda...

  • Java-8-Optional类

    Java-8-Optional类 java8新特性之Optional类 空指针异常是一个运行时异常,对于这一类异常...

  • Java 8 新特性

    Java 8 新特性 声明:java8新特性系列为个人学习笔记,参考地址点击这里,侵删!! Java 8 (又称为...

  • Java8学习笔记-1

    Java8学习笔记-1序在java11即将面世的时候,终于开始行动学习java8的特性。目前没有机会实践,只是跟着...

网友评论

      本文标题:Java8特性学习笔记(三) Optional

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