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);
}
}

​程序运行结果​

{name=AnswerAIL}

 

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");
}

}

程序运行结果

20191008125000
none
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);
}