开发使用Optional类的代码
关于 null 的问题
大多数编程语言都有一种表示没有值的数据类型,它有许多名称
NULL, nil, None, Nothing
1965年 Tony Hoare 在 ALGOL W 中引入了 null 类型,它被认为是计算机科学中最严重的错误之一
- null 有什么问题
String summary =
book.getChapter(10)
.getSummary().toUpperCase();
如果这些方法中的任何一个返回一个 null 引用(例如,如果书中没有第十章) ,那么在运行时停止程序时将抛出一个 NullPointerException(NPE)
- 避免NPE
检查null
String summary = "";
if(book != null) {
Chapter chapter = book.getChapter(10);
if(chapter != null) {
if(chapter.getSummary() != null) {
summary = chapter.getSummary()
.toUpperCase();
}
}
}
检查null的问题
- 不知道结构中的任何对象是否可以为空,要检查每个对象是否有这个值。它不太实用,并且损害了可读性。
- 检查 null 真的值得吗?如果这些对象永远不应该为空呢?通过检查 null,我们将隐藏错误并且不处理它。
- 那么使用什么作为默认值会更好呢?空字符串还是null?
为了解决这个问题,java8引入了java.util.Optional
Optional类
这个类的为可以为null的对象封装一个可选值。
- 如果可能为null的属性,我门可以这么设置属性
class Chapter {
private Optional<String> summary;
// Other attributes and methods
}
如果该属性有值,Optional 类只是包装它。否则,一个空值由 Optional.empty ()方法表示,该方法返回 Optional 的单例实例。
通过使用这个类而不是 null避免NPE,同时可以使用 Optional 的有用方法
创建Optional实例
Optional构造方法私有化
- 一个空的Optional
Optional<String> summary = Optional.empty();
该方法的value为null
- 确定一个对象不是 null
Optional<String> summary = Optional.of("A summary");
1.如果非null,则返回带有指定值的 Optional 实例
2.为null,返回空 Optional
- 你想知道一个 Optional 是否包含一个值
if( summary.isPresent() ) {
// Do something
}
- 或者以一种更实用的方式
summary.ifPresent(s -> System.out.println(s));
// Or summary.ifPresent(System.out::println);
这个方法仅当 Optional 包含值才进行Consumer接口函数
- 获得一个可选使用的值
String s = summary.get();
如果 Optional 不包含值,这个方法将抛出一个 java.util.NoSuchElementException 异常,因此最好使用 ifPresent ()方法
- 如果我们想在 Optional 不包含值的情况下返回一些东西,我们可以使用其他三种方法
1.当 Optional 为空时,orElse ()方法返回参数(必须是类型 t,在本例中是 String)
String summaryOrDefault = summary.orElse("Default summary");
2.orElseGet ()方法采用Supplier<? extends T>作为一个参数,当 Optional 为空时返回一个值。否则,它返回封装的值
String summaryOrDefault =
summary.orElseGet( () -> "Default summary" );
3.orElseThrow ()方法Supplier<? extends X> 是当 Optional 为空时抛出的异常类型。否则,它返回封装的值。
String summaryOrException =
summary.orElseThrow( () -> new Exception() );
其他类型的Optional
像Stream一样,Optional 类也有一些版本来处理原语,OptionalInt,OptionalLong 和 OptionalDouble,所以你可以使用 OptionalInt 来代替Optional
OptionalInt optionalInt = OptionalInt.of(1);
int i = optionalInt.getAsInt();
不鼓励使用这些原语版本,特别是因为它们缺少三种有用的方法: filter ()、 map ()和 flatMap ()。而且由于 Optional 只包含一个值,装箱/取消装箱原语的开销并不显著
filter
如果存在一个值并与给定的预测值相匹配,filter ()方法将返回 Optional。否则,返回一个空的 Optional
map
Map ()方法通常用于从一种类型转换到另一种类型。如果该值存在,使用Function< ? super T, ? extends U >转换入参。
int summaryLength = summary.map(s -> s.length()).orElse(0);
flapMap ()
但它采用的参数类型是Function<? super T, Optional>,如果值存在,它返回应用提供的函数产生的Optional。否则,它将返回一个空 Optional
总结
- Optional
类封装了一个可选值,即可以为null的对象。 - 空值由Optional.empty()方法表示。
- 可以使用of()方法将对象包装为可选的,但是,如果对象为null,则会引发NullPointerException。
- 如果可选实例的值为非null,则方法ofNullable()返回一个具有指定值的可选实例。否则,它将返回一个空的可选值。
- 要获取可选项的值,请使用get()方法,但是如果可选项不包含值,它将抛出java.util.NoSuchElementException,因此最好使用ifPresent()方法,该方法将Consumer< T>作为参数,仅当Optional包含值时才执行。
- 当Optional为空时,orElse()方法返回参数,否则返回封装的值。
- orElseGet()方法接受一个Supplier,该Supplier在Optional为空时返回一个值。否则,它将返回封装的值。
- orElseThrow()方法接受一个Supplier,该Supplier在Optional为空时返回一个异常。否则,它将返回封装的值。
Comments | 0 条评论