Java开发 | Optional 让null处理多一种选择

作者:threedayman

来源: 恒生LIGHT云社区

前言

在开发过程中,经常会遇到 NullPointerException 运行时异常。为了能更好的处理空指针问题, 从java 1.8版本后提供了 java.util.Optional 工具类。

Optional API 介绍

属性值

private final T value;
private static final Optional<?> EMPTY = new Optional<>();
  • value:Optional对象持有的需要进行业务对象。
  • EMPTY: 为value 为空的 Optional 对象。

Optional 对象创建

public static<T> Optional<T> empty() {
	Optional<T> t = (Optional<T>) EMPTY;
	return t;
}
public static <T> Optional<T> of(T value) {
	return new Optional<>(value);
}
public static <T> Optional<T> ofNullable(T value) {
	return value == null ? empty() : of(value);
}
  • empty() 创建一个value为null的 Optional对象。
  • of(T value) value不允许为null。
  • ofNullable(T value) 最常用的Optional对象创建方式,value允许为null。

业务对象判空和对象获取

public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}
  
public boolean isPresent() {
    return value != null;
}
  • 通过get方法 我们可以获取到value对象,注意如果value为null 会抛出 NoSuchElementException 异常
  • isPresent 方法用来判断value 是否为空

有些小伙伴可能有疑问了,这个工具类并没有比之前写的非空判断更优雅。比如

if(object != null){
  //doSomething
}

在java 1.8版本后,提供了函数式接口。下面我们来看下Optional 结合函数式接口的例子,通过例子来进一步感受下带来的变化。

java.util.Optional#ifPresent

public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
      consumer.accept(value);
}

例子

Column col = getColumn();
Optional.ofNullable(col).ifPresent(System.out::println);

java.util.Optional#filter

public Optional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    if (!isPresent())
        return this;
    else
    return predicate.test(value) ? this : empty();
}

例子

Column column = getColumn();
Optional.ofNullable(column).filter(col -> "length".equals(col.getName())).ifPresent( t -> System.out.println("exist"));

java.util.Optional#map java.util.Optional#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));
	}
}

例子

public class Table{
	public Optional<Column> getColumn(Table t){
		//doSomthing
	}
}

Table table = new Table();
Optional.ofNullable(table).map(Table :: getColumn);
Optional.ofNullable(table).flatMap(Table :: getColumn);

通过map和flatMap我们得到的结果如下图

640.png

  • map方法将返回结果又套了一层Optional。
  • flatMap直接将结果返回。

java.util.Optional#orElse java.util.Optional#orElseGet

public T orElse(T other) {
	return value != null ? value : other;
}

public T orElseGet(Supplier<? extends T> other) {
	return value != null ? value : other.get();
}

例子

Column column = getColum();
Optional.ofNullable(column).orElse(new Column("default"));
Optional.ofNullable(column).orElseGet(() ->  new Column("default"));

java.util.Optional#orElseThrow

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
	if (value != null) {
		return value;
	} else {
		throw exceptionSupplier.get();
	}
}

例子

Column column = getColum();
Optional.ofNullable(column).orElseThrow(RuntimeException::new);

使用样例

我们有如下数据结构的Database对象,如果要获取到name属性我们可以按照下面那样操作

640 (1).png

database.getTable().getColumn().getName();

看起来上面的代码可读性很好,但是不是每个database 都能获取到对应的table,所以上面的代码存在NPE的风险

我们可以按照下面的方式修改

if(database != null){
	Table table = database.getTable();
	if(table != null){
		Column column = table.getColumn();
		if(column != null){
			String name = column.getName()
		}
	}
}

为了避免空指针我们使用了很多的if逻辑判断,造成代码可读性大大降低。

Optional.ofNullable(database).flatMap(DataBase::getTable)
                             .flatMap(Table::getColumn)
                             .map(Column::getName)
                             .orElse("UNKNOW");

通过Optional工具的使用 增加了代码的可读性。掌握Optional类后,对于空指针预防我们又多了一种处理选择。

引用

[1] https://www.oracle.com/technical-resources/articles/java/java8-optional.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值