java8使用optional简化编程

本文深入解析Java 8中的Optional类,探讨其内部实现原理,包括构造器、静态工厂方法及主要成员方法如get()、ifPresent()、filter()、map()、flatMap()等。通过对比传统空值检查方式,展示Optional如何简化代码并避免NullPointerException。最后,提供了一个使用Optional优化复杂多层判断的实例。

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包装

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值