optional 是一个泛型类,可以将它理解为一个包装器。它包含一个value和一个空对象:
private final T value;
//空对象的创建
private static final Optional<?> EMPTY = new Optional<>();
//空对象创建的唯一指定构造器
private Optional() {
this.value = null;
}
此外它还有一个私有构造器,用于传值创建对象:
//value为空则抛异常
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
optional的创建对外提供了三个方法:
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
//value不能为空
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
//value可为空
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
-----------------------------题外话-----------------------------
为什么要用of命名,个人的理解是这样的:
optional中文译为可选的,of代表了部分和整体的关系。
Optional<Integer> op=Optional.of(num);
结果部分 = 可从num里选择 ; ——>只能选num不然就抛NPE
Optional<Integer> op=Optional.ofNullable(num);
结果部分 = 可从null和num里选择 ; ——>可以是null
-----------------------------回归正题-----------------------------
下面介绍一下optional的一些方法:
一、get()可以把非空的元素取出来
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
二、is/if Present(…) 用于判断value是不是空,当然非空时可以执行相应的操作
public boolean isPresent() {
return value != null;
}
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
bad code!!!千万别这么用
Optional<Student> student=queryDBStuent("20200401");
if(student.isPresent()){
doSomething(student.get());
}
差强人意
Optional<Student> student=queryDBStuent("20200401");
student.ifPresent(this::doSomething);
三、filter用于按条件筛选值,条件是必要的。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
四、map用于value的映射,可以将某类value映射为其他类型,或者对每个value进行包装。
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));
}
}
注释中的例子薅出来看看:
Here, {@code findFirst} returns an {@code Optional}, and then {@code map} returns an {@code Optional} for the desired file if one exists.
Optional<FileInputStream> fis =names.stream()
.filter(name -> !isProcessedYet(name))
.findFirst()
.map(name -> new FileInputStream(name));
当value不为空时,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));
}
}
五、三个末端操作:
没有值则传入默认值
public T orElse(T other) { return value != null ? value : other;}
没有值则生产默认值
public T orElseGet(Supplier<? extends T> other) {return value != null ? value : other.get();}
没有值就抛异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
六、optional使用例子:
对于一个复杂的多层判断:
public Integer demo01(Student student){
if(student!=null){
if(student.getAge()<9){
if(student.getAge()>3){
return student.getAge()+1;
}
return student.getAge()+2;
}
}
return -1;
}
使用optional使代码非常简洁:
public Integer demo02(Student student){
return Optional.ofNullable(student)
.filter(s->s.getAge()<9)
.map(s->s.getAge()>3?s.getAge()+1:s.getAge()+2)
.orElse(-1);
}
总结:处理集合用流处理,处理一般对象用optional包装
本文深入解析Java 8中的Optional类,探讨其内部实现原理,包括构造器、静态工厂方法及主要成员方法如get()、ifPresent()、filter()、map()、flatMap()等。通过对比传统空值检查方式,展示Optional如何简化代码并避免NullPointerException。最后,提供了一个使用Optional优化复杂多层判断的实例。
658

被折叠的 条评论
为什么被折叠?



