您的位置 首页 java

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

在开发过程中,经常会遇到 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).flat map (Table :: getColumn);
  

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

  • 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属性我们可以按照下面那样操作

 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类后,对于空指针预防我们又多了一种处理选择。

文章来源:智云一二三科技

文章标题:Java开发 | Optional 让null处理多一种选择

文章地址:https://www.zhihuclub.com/187055.shtml

关于作者: 智云科技

热门文章

网站地图