乐趣区

关于java:Java-8-特性之Optional用法详解

前言

NPE(NullPointerException)始终是 Java 程序员最疾恶如仇的异样,简短的非空校验使代码的可读性和优雅性都大大降低。那么本篇文章,笔者将具体介绍一下 Java 8 引入的个性 –Optional类,看看它是如何防止空指针异样的。

什么是 Optional?

Optional 是一个容器对象,它可能蕴含或不蕴含非空值。如果存在值,isPresent()将返回 true,而 get()则返回该值。提供了取决于所蕴含值的存在与否的其余办法,例如 orElse()(如果值不存在,则返回默认值)和 ifPresent()(若值存在,则执行一段代码)。这是一个基于值的类;对 Optional 实例应用身份敏感操作(包含援用相等(==)、身份哈希码或同步)可能会产生不可预测的后果,应防止

Optional 解决了什么问题?

在 Java 8 之前,咱们进行对象校验是这样的:

public String getCity(User user){if(user != null){Address address = user.getAddress();
        if(address != null){return address.getCity();
        }else{return "北京市";}
    }else{return "北京市";}
}

Java 8 写法:

public String getCity(User user){return Optional.ofNullable(user)
        .map(u -> u.getAddress())
        .map(address -> address.getCity())
        .orElse("北京市");

}

办法详解

empty

形容

返回空的 Optional 实例。

源码
public static<T> Optional<T> empty() {@SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}
用法
Optional<Object> empty = Optional.empty();

创立了一个空的 Optional 对象,如果此时调用 get()办法,会抛出 NoSuchElementException

Optional<Object> empty = Optional.empty();
System.out.println(empty.get());// 抛出 NoSuchElementException

of(T value)

形容

为非 Null 值创立一个 Optional,传入参数不能为 null,否则会抛出 NullPointerException。

源码
public static <T> Optional<T> of(T value) {return new Optional<>(value);
}
用法
Optional<String> userName = Optional.of("userName");

如果传入 null,则会抛出 NullPointerException

Optional<String> userName = Optional.of(null);// 抛出 NullPointerException

ofNullable(T value)

形容

创立可为空的 Optional,如果为非空,返回 Optional 形容的指定值,否则返回空的 Optional。

源码
public static <T> Optional<T> ofNullable(T value) {return value == null ? empty() : of(value);
}
用法
Optional<String> userName = Optional.ofNullable("userName");

get()

形容

如果在这个 Optional 中蕴含这个值,返回值,否则抛出异样:NoSuchElementException。

源码
public T get() {if (value == null) {throw new NoSuchElementException("No value present");
    }
    return value;
}
用法
Optional<String> userName = Optional.ofNullable("userName");
System.out.println(userName.get());// 输入 userName

isPresent()

形容

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

源码
public boolean isPresent() {return value != null;}
用法
Optional<String> userName = Optional.ofNullable("userName");
System.out.println(userName.isPresent());// 输入 true
Optional<String> empty = Optional.ofNullable(null);
System.out.println(empty.isPresent());// 输入 false

ifPresent(Consumer<? super T> consumer)

形容

如果值存在则应用该值调用 consumer , 否则不执行任何操作。

要了解 ifPresent 办法,首先须要理解 Consumer 类。简答地说,Consumer 类蕴含一个形象办法。该形象办法对传入的值进行解决,但没有返回值。Java8 反对不必接口间接通过 lambda 表达式传入参数。
如果 Optional 实例有值,调用 ifPresent()能够承受接口段或 lambda 表达式。

源码
public void ifPresent(Consumer<? super T> consumer) {if (value != null)
        consumer.accept(value);
}
用法
Optional<String> userName = Optional.ofNullable("userName");
userName.ifPresent((value) -> System.out.println(value.length()));// 输入 8
Optional<String> empty = Optional.ofNullable(null);
empty.ifPresent((value) -> System.out.println(value.length()));// 无输入,此时 Optional 为空值,不执行操作

filter(Predicate<? super T> predicate)

形容

如果值存在,并且这个值匹配给定的 predicate,返回一个 Optional 用以形容这个值,否则返回一个空的 Optional。

源码
public Optional<T> filter(Predicate<? super T> predicate) {Objects.requireNonNull(predicate);
    if (!isPresent())
        return this;
    else
        return predicate.test(value) ? this : empty();}
用法
Optional<String> userName = Optional.ofNullable("userName");
Optional<String> filterUserName1 = userName.filter((value) -> value.length() > 4);
System.out.println(filterUserName1.get());// 输入 userName
Optional<String> filterUserName2 = userName.filter((value) -> value.length() < 4);
System.out.println(filterUserName2.get());// 抛出 NoSuchElementException,因为此时没有找到匹配的值,返回一个空的 Optional

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

形容

如果有值,则对其执行调用映射函数失去返回值。如果返回值不为 null,则创立蕴含映射返回值的 Optional 作为 map 办法返回值,否则返回空 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));
    }
}
用法
Optional<String> userName = Optional.ofNullable("userName");
Optional<String> mapUserName = userName.map((value) -> value.toUpperCase(Locale.ROOT));
System.out.println(mapUserName.get());// 输入 USERNAME 

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

形容

如果值存在,返回基于 Optional 蕴含的映射办法的值,否则返回一个空的 Optional,此办法相似于 map(Function),但提供的 mapper 的返回值必须是 Optional,如果调用,flatMap 不会用附加的 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));
    }
}
用法
Optional<String> userName = Optional.ofNullable("userName");
Optional<String> flatMapUserName = userName.flatMap((value) ->
                     Optional.of(value.toUpperCase(Locale.ROOT)) //mapper 的返回值必须为 Optional
);
System.out.println(flatMapUserName.get());// 输入 USERNAME

orElse(T other)

形容

如果存在该值,返回值,否则返回 other。

源码
public T orElse(T other) {return value != null ? value : other;}
用法
Optional<String> userName = Optional.ofNullable("userName");
System.out.println(userName.orElse("mobile"));// 输入 userName
Optional<Object> empty = Optional.empty();
System.out.println(empty.orElse("mobile"));// 输入 mobile

orElseGet(Supplier<? extends T> other)

形容

如果存在该值,返回值,否则触发 other,并返回 other 调用的后果。orElseGet 与 orElse 办法相似,区别在于失去的默认值。orElse 办法将传入的字符串作为默认值,orElseGet 办法能够承受 Supplier 接口 的实现用来生成默认值。

源码
public T orElseGet(Supplier<? extends T> other) {return value != null ? value : other.get();
}
用法
Optional<String> userName = Optional.ofNullable("userName");
System.out.println(userName.orElseGet(() -> "mobile"));// 输入 userName
Optional<Object> empty = Optional.empty();
System.out.println(empty.orElseGet(() -> "mobile"));// 输入 mobile

orElseThrow(Supplier<? extends X> exceptionSupplier)

形容

如果存在该值,返回蕴含的值,否则抛出由 Supplier 继承的异样

源码
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {if (value != null) {return value;} else {throw exceptionSupplier.get();
    }
}
用法
try {Optional<String> userName = Optional.ofNullable("userName");
    System.out.println(userName.orElseThrow(Exception::new));// 输入 userName
} catch (Exception e) {e.printStackTrace();
}
try {Optional<Object> empty = Optional.empty();
    System.out.println(empty.orElseThrow(Exception::new));
} catch (Exception e) {e.printStackTrace(); // 异样捕捉
}

总结

以上便是 Optional 的各个办法的用法介绍,还是倡议大家纯熟应用,这样能让本人的代码变得更加优雅。

退出移动版