Java8 Optional 类使用
原创
©著作权归作者所有:来自51CTO博客作者Jaemon的原创作品,请联系作者获取转载授权,否则将追究法律责任
public final
class Optional { … }
Optional 类方法说明
-
of
: 为非 null 的值创建一个 Optional。 创建对象时传入的参数不能为 null。 如果传入参数为 null, 则抛出 NullPointerException -
ofNullable
: 为指定的值创建一个 Optional, 如果指定的值为 null, 则返回一个空的 Optional -
isPresent
: 如果值存在返回 true, 否则返回 false -
get
: 如果 Optional 有值则将其返回, 否则抛出 NoSuchElementException -
ifPresent
: 如果 Optional 实例有值则为其调用 consumer, 否则不做处理 -
orElse
: 如果有值则将其返回, 否则返回指定的其它值 -
orElseGet
: orElseGet 与 orElse 方法类似, 区别在于得到的默认值。 orElse 方法将传入的字符串作为默认值, orElseGet 方法可以接受 Supplier 接口的实现用来生成默认值 -
orElseThrow
: 如果有值则将其返回, 否则抛出 supplier 接口创建的异常 -
map
: 如果有值, 则对其执行调用 mapping 函数得到返回值。 如果返回值不为 null, 则创建包含 mapping 返回值的 Optional 作为 map 方法返回值, 否则返回空 Optional -
flatMap
: 如果有值, 为其执行 mapping 函数返回 Optional 类型返回值, 否则返回空 Optional -
filter
: 如果有值并且满足断言条件返回包含该值的 Optional, 否则返回空 Optional
案例分析
public class AnswerApp {
public static void main(String[] args) throws Exception {
answer(null);
}
private static void answer(User user) {
user = Optional.ofNullable(user).orElse(new User());
// 上一行代码 等价于 下一行代码
// user = (user == null) ? new User() : user;
Map<String, String> map = Maps.newConcurrentMap();
map.put("name", Optional.ofNullable(user.getName()).orElse("AnswerAIL"));
// 上一行代码 等价于 下一行代码
// map.put("name", (user.getName() == null) ? "AnswerAIL" : user.getName());
System.out.println(map);
}
}
程序运行结果
orElse 和 orElseGet 的区别
public class AnswerApp {
public static void main(String[] args) throws Exception {
String name = "AnswerAIL";
System.out.println(Optional.of(name).orElse(AnswerApp.getName()));
System.out.println();
System.out.println(Optional.of(name).orElseGet(AnswerApp::getName));
System.out.println("\n");
String key = null;
System.out.println(Optional.ofNullable(key).orElse(AnswerApp.getName()));
System.out.println();
System.out.println(Optional.ofNullable(key).orElseGet(AnswerApp::getName));
}
private static String getName() {
System.out.println("execute method getName...");
return "answer";
}
}
程序运行结果
execute method getName...
AnswerAIL
AnswerAIL
execute method getName...
answer
execute method getName...
answer
结果验证说明:
当 Optonal 的值是空值时, 无论 orElse 还是 orElseGet 都会执行; 而当返回的 Optional 有值时, orElse 会执行, 而 orElseGet 不会执行。 因此, orElseGet 方法在性能上要优于 orElse 方法
orElseThrow 方法
public class AnswerApp {
public static void main(String[] args) throws Exception {
String value = "optional";
System.out.println("result: " + Optional.ofNullable(value).orElseThrow(() -> new Exception("value is null")));
System.out.println();
Thread.sleep(1000);
String name = null;
System.out.println("result: " + Optional.ofNullable(name).orElseThrow(() -> new Exception("name is null")));
}
}
程序运行结果
result: optional
Exception in thread "main" java.lang.Exception: name is null
at com.answer.AnswerApp.lambda$main$1(AnswerApp.java:40)
at java.util.Optional.orElseThrow(Optional.java:290)
at com.xiwei.AnswerApp.main(AnswerApp.java:40)
优雅判空
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Response {
private int code;
private String msg;
private Result result;
}
@Data
@AllArgsConstructor
class Result {
private int totalCount;
private RltData data;
}
@Data
@AllArgsConstructor
class RltData {
private String orderNo;
private BigDecimal orderAmt;
private Byte status;
}
public class AnswerApp {
public static void main(String[] args) {
RltData data = new RltData("20191008125000", new BigDecimal(10000), (byte)1);
Result result = new Result(10, data);
Response response = new Response(1000, "success", result);
String rlt = checkRlt(response);
System.out.println(rlt);
response = new Response(1000, "success", null);
rlt = checkRlt(response);
System.out.println(rlt);
result = new Result(10, null);
response = new Response(1000, "success", result);
rlt = checkRlt(response);
System.out.println(rlt);
}
private static String checkRlt(Response response) {
return Optional.ofNullable(response)
.map(Response::getResult)
.map(Result::getData)
.map(RltData::getOrderNo).orElse("none");
}
}
程序运行结果
优雅判空2
不使用Optional
String brand = null;
if (null != person) {
if (null != person.getCar()) {
if (null != person.getCar().getWheel()) {
brand = person.getCar().getWheel().getBrand();
}
}
}
使用Optional
brand = Optional.ofNullable(person) // 转换为Optional进行包裹
.map(p -> p.getCar()) // 获取Car对象
.map(car -> car.getWheel()) // 获取Wheel对象
.map(wheel -> wheel.getBrand()) // 获取brand
.orElse("玛莎拉蒂"); // 如果中间有对象为null,则返回默认值"玛莎拉蒂"
如上代码,经过改造后,代码的可读性得到了提高,而写代码的成本却大大降低。上面使用Optional后,无论person为null,或者其内部的car为null,或者wheel对象为null,都不会出现NPE,而是会返回默认的“玛莎拉蒂”。
基于JDK8中Optional写出可读性高的代码
map & flatMap
使用 map方法 返回对象,使用 flatMap方法 返回 Optional<对象>
// 用 map 方法
public T getXXX() {
return t;
}
// 用 flatMap 方法
public Optional<T> getXXX() {
return Optional.of(t);
}