Optional简介
Optional 类的引入主要是为了解决解决空指针异常的问题。Optional是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。
Optional可以帮助我们简化代码,给我们的判空操作提供了一种标准的写法,强制我们考虑空值的情况。
类方法
方法 | 描述 |
---|---|
static Optional empty() | 返回空的Optional实例 |
boolean equals(Object obj) | 判断其他对象是否等于 Optional |
Optional filter(Predicate<? super predicate) | 如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional |
Optional flatMap(Function<? super T,Optional> mapper) | 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
T get() | 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException |
int hashCode() | 返回存在值的哈希码,如果值不存在 返回 0。 |
void ifPresent(Consumer<? super T> consumer) | 如果值存在则使用该值调用 consumer , 否则不做任何事情。 |
boolean isPresent() | 如果值存在则方法会返回true,否则返回 false。 |
Optional map(Function<? super T,? extends U> mapper) | 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 |
static Optional of(T value) | 返回一个指定非null值的Optional。 |
static Optional ofNullable(T value) | 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。 |
T orElse(T other) | 如果存在该值,返回值, 否则返回 other。 |
T orElseGet(Supplier<? extends T> other) | 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 |
T orElseThrow(Supplier<? extends X> exceptionSupplier) | 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 |
String toString() | 返回一个Optional的非空字符串,用来调试 |
fangwen1
应用举例
测试代码
package com.lin.missyou.optional;
import org.junit.Test;
import java.util.Optional;
public class OptionalTest {
@Test
public void testOptional(){
/**构建Optional*/
//构建空的Optional
Optional<String> empty = Optional.empty();
//构建Optional传入空值会报错
// Optional<String> t1 = Optional.of(null);
//构建Optional允许传入空值
Optional<String> t2 = Optional.ofNullable("a");
// String s = t2.get();
// t2不为空时执行ifPresent()中的语句
// t2.ifPresent(t-> System.out.println(t)); //lambada表达式写法
t2.ifPresent(System.out::println); //方法引用写法
//传统写法
// String s = "默认值";
// if(null != t2){
// s = t2.get();
// }else{
//
// }
//应用Optional的写法
String s = t2.orElse("默认值");
System.out.println(s);
//Optional链式操作 .map()返回值会再次包装成Optional类
t2.map(t->t+"b").ifPresent(System.out::println);
}
}
构建 Optional 实例
empty()
这个类型的对象可能包含值,也可能为空。你可以使用同名方法创建一个空的 Optional。
尝试访问 empty 变量的值会导致 NoSuchElementException。
Optional<String> empty = Optional.empty();
empty.get();
of()和ofNullable()
我们可以使用 of() 和 ofNullable() 方法创建包含值的 Optional。两个方法的不同之处在于如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException。我们并没有完全摆脱 NullPointerException。因此,你应该明确对象不为 null 的时候使用 of()。如果对象即可能是 null 也可能是非 null,你就应该使用 ofNullable() 方法:
Optional<String> t1 = Optional.of(null);
访问 Optional 对象的值
get()
Optional的get()方法,如果Optional的值是空值在get()取值的时候就会直接报错,这就是Optional的意义所在。
不用Optional的时候会直接把空值赋值给s,此处不会报错,空指针异常令我们是否头疼。如果在赋值时不产生异常,空指针异常会成为隐藏的错误,随着我们函数调用栈变深会越来越难以调试。如果空指针的问题贯穿了整个函数调用栈一直到最后一个函数才被发现,在溯源的时候就需要跟踪调试栈上的所有函数。
Optional<String> t2 = Optional.ofNullable(null);
String s = t2.get();
ifPresent()
ifPresent() 当t2不为 null 的时候才会执行传入的方法。该方法除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就执行传入的 Lambda 表达式。
Optional<String> t2 = Optional.ofNullable("a");
//t2.ifPresent(t-> System.out.println(t)); //lambada表达式写法
t2.ifPresent(System.out::println); //方法引用写法
orElse() 和 orElseGet()
Optional 类提供了 API 用以返回对象值,或者在对象为空的时候返回默认值。
这里你可以使用的第一个方法是 orElse(),如果有值则返回该值,否则返回传递给它的参数值,我们之前经常给变量赋值如果为空则给一个默认值,不为空时赋值,用Optional的orElse()方法改写代码就变得非常简洁。
Optional<String> t2 = Optional.ofNullable("a");
//传统写法
// String s = "默认值";
// if(null != t2){
// s = t2.get();
// }else{
//
// }
//应用Optional的写法
String s = t2.orElse("默认值");
System.out.println(s);
orElse() 和 orElseGet() 的不同之处
@Test
public void testOptional(){
User user = null;
System.out.println("Using orElse");
User result = Optional.ofNullable(user).orElse(createNewUser());
System.out.println("Using orElseGet");
User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
}
private User createNewUser(){
System.out.println("createNewUser");
return new User("小明","123456");
}
由执行结果可以看出,当对象为空而返回默认对象时,orElse()和orElseGet()并无差异。
User user = new User("小红","12345");
System.out.println("Using orElse");
User result = Optional.ofNullable(user).orElse(createNewUser());
System.out.println("Using orElseGet");
User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
当user不为空时,两个方法都会返回对应的非空值。不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象。
在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。
orElseThrow()
如果存在该值,返回包含的值,否则抛出传入的异常
public Theme getThemeByNameWithSpu(@PathVariable String name){
Optional<Theme> themeOptional = themeService.findByname(name);
return themeOptional.orElseThrow(()-> new NotFoundException(30003));
}
Optional的链式操作
你可以链接组合Optional的大部分方法,因为它们都返回Optional的对象。
//Optional链式操作 .map()返回值会再次包装成Optional类
t2.map(t->t+"b").ifPresent(System.out::println);