Java 8 引入的一个 Optional 类。Optional 类主要解决的问题是空指针异常(NullPointerException)
本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。
//传入的值为空返回一个Optional 不为空返回泛型为传入对象的Optional
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
//获取对象
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
//Optional不为空返回 true Optional为空返回false
public boolean isPresent() {
return value != null;
}
过滤值
filter() 接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
例子
TestDto dto=new TestDto("@1223","1788");
Optional<TestDto> testDto = Optional.ofNullable(dto)
.filter(u -> u.getName() != null && u.getName().contains("@"));
转换值
map() 和 flatMap()
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));
}
}
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));
}
}
例子
//map() 对值应用(调用)作为参数的函数,然后将返回的值包装在 Optional 中
//如果获取的值为空则赋予一个值
TestDto dto=new TestDto("@1223","1788");
String s = Optional.ofNullable(dto).map(TestDto::getName).orElse("@123");
//flatMap() 需要函数作为参数,并对值调用这个函数,然后直接返回结果
TestDto dto=new TestDto("@1223","1788");
dto.setId("1");
String id = Optional.ofNullable(dto).flatMap(TestDto::getId).orElse("0");
返回默认值
Optional 类提供了 API 用以返回对象值,或者在对象为空的时候返回默认值。
orElse()
当optional值不存在时,调用orElse()返回orElse()的参数,如果optional的值存在时返回optional的值
orElseGet()
当optional值不存在时,调用orElseGet()中接口调用的返回值,如果optional的值存在时返回optional的值
orElse(),它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值:
public T orElse(T other) {
return value != null ? value : other;
}
TestDto dto=new TestDto("@1223","1788");
TestDto dto1=null;
TestDto dto2=new TestDto("@1223","1788");
//这里 对象是空的,所以返回了作为默认值的 对象。
TestDto testDto1 = Optional.ofNullable(dto1).orElse(dto);
/如果对象的初始值不是 null,那么默认值会被忽略:
TestDto testDto2 = Optional.ofNullable(dto2).orElse(dto);
orElseGet() 。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
Optional.ofNullable(dto).orElseGet(()->dto2);
orElse() 和 orElseGet() 的不同之处
public static void main(String[] args){
List<Integer> list = Arrays.asList(23,1,3);
//List<Integer> list = Arrays.asList();
int myElse = list.stream().reduce(Integer::sum).orElse(get("myElse"));
int myElseGet = list.stream().reduce(Integer::sum).orElseGet(() -> get("myElseGet"));
System.out.println("myElse的值"+myElse);
System.out.println("myElseGet的值"+myElseGet);
}
public static int get(String name){
System.out.println(name+"执行了该方法");
return 1;
}
观察有值和为空的执行结果发现当对象为空,行为并无差异,两个 对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse() 方法执行get方法。与之相反,orElseGet() 方法不执行get方法。
除了 orElse() 和 orElseGet() 方法,Optional 还定义了 orElseThrow() API —— 它会在对象为空的时候抛出异常,而不是返回备选的值:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
TestDto orElseThrow = Optional.ofNullable(dto1).orElseThrow(() -> new RuntimeException());