欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java8之新特性--Optional类型详解

程序员文章站 2022-06-07 12:14:47
...

Java8中新增了许多新的特性,分别是Lambda,方法引用(一般配合Lambda使用),Date/Time API,Stream,Optional,Base64加密,Interface支持默认方法和静态方法,另外还新增了一些新引擎工具,新增了对JavaScript的解释器-Nashorn。

本章主要讲下Optional类型的使用:

1、概念:Optional<>类型提供了一个容器,主要是检查容器中的元素是否为NULL。提到容器,很多Java小伙伴想到了List、Map、Set等,Optional最大的区别就是它只能插入一个元素,并会判断插入的元素是否为NULL

2、Optional 版本:@since 1.8,可以查看源码对照下面的API详细的介绍来学习

2、常用API介绍

(1)static Optional empty()

定义:构建一个空的Optional容器,相当与List list = new ArrayList(),里面没有任何元素,但在堆中已分配了空间

源码:

private static final Optional<?> EMPTY = new Optional<>();

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

分析:empty()方法中调用静态常量EMPTY 使用实例化new的方式构建一个空的容器

(2)static Optional of(T value)

定义:向Optional容器中插入一个元素,并检查这个元素是否为NULL,如果为NULL就抛异常;如果不为NULL,就会把这个元素插进去,并返回Optional对象

源码:

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

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

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

分析:of()方法中实例化了一个Optional容器,并将传入的值插入到容器中,在constructor方法中,调用Objects类的requireNonNull() 方法;如果值为NULL,就抛出空指针异常

(3)static Optional ofNullable(T value)   (empty()与of()方法的结合)

定义:向Optional容器中插入一个元素,并检查这个元素是否为NULL,如果为NULL,会构建一个空的容器,并返回Optional对象;如果不为NULL,就会把这个元素插进去,并返回Optional对象

ofNullable()与of()的最大区别就在于前者遇到NULL时,不做处理,会返回一个空的Optional容器对象,后者遇到NULL时,直接抛空指针(NullPointerException)异常

源码:

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

分析:ofNullable()方法使用三目运算,如果传入的对象为NULL,调用empty()方法,构建一个空的Optional容器对象;如果不为NULL,调用of()方法,将该元素插入到容器中,并返回Optional容器对象

调用的empty()方法与of(value)方法是对应上方的(1)(2)讲的两个方法

(4)T get()

定义:获取Optional容器中的元素,与List的get(int index)方法类似,由于Optional容器中只能存入一个值,所以get时,无需指定索引

源码:(实例方法,需要使用Optional对象调用)

private final T value;

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

分析:get()方法会判断当前容器中是否存在元素,如果不存在,会抛出NoSuchElementException异常;如果存在会返回该元素

(5)boolean isPresent()

定义:判断当前容器中的元素是否为NULL,如果为NULL,返回true,否则false(一般该方法与get()结合使用)

源码:

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

(6)T orElseGet(Supplier<? extends T> other)

定义:判断当前容器中的元素是否为NULL,如果不为NULL,返回该元素;如果为NULL,执行lambda参数(方法体)

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

例如:

static String print() {
    System.out.println("Hello world!");
    return "success";
}

public static void main(final String... args) {
    System.out.println(Optional.of("A").orElseGet(() -> print()));
}

注:() -> print() 是lambda表达式的写法(lambda允许将方法体当成参数传递给另一个方法)后面章节会讲到!

(7)T orElseThrow(Supplier<? extends X> exceptionSupplier) 

定义:检查容器中的元素是否为NULL,如果不为NULL,正常返回该元素;如果为NULL,抛出传入的异常(自定义异常)

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

例如:(频繁会用到)

public Document findById(String id) throws UCException {
    return documentRepository.findById(id).orElseThrow(
            () -> new UCException(HttpStatus.NOT_FOUND, ErrorCode.DOCUMENT_NOT_FOUND, id));
}

分析:Supplier是@FunctionInterface函数式接口,这里先不做了解,后面章节会讲到!事例中的fingById()方法是从数据库中通过ID查询实体,如果没有查询到,结果为NULL,这里会直接抛出预先定义的异常,只需在Controller统一捕获就可以了,这样的话就不用在Service中判断==Null,不用特意通知前端了,非常简单实用!

以上就是开发中经常会用到的一些Optional API!

本章节就先讲到这里,对Optional类型的使用还有不明白的,或者在整合到项目中出错的,欢迎加博主QQ:1402218191 !