Version: Next

Optional类

info

优雅的处理一种大家经常写的代码

if (userName != null) { // 判空
//...
} else {
// ..
}

Java的经典送命祖传异常,空指针异常

  • Optional<T> 类,java.util.Optional是一个容器类
    • 它可以保存T的值,代表这个值存在
    • 或者仅仅保存null,表示这个值不存在
  • 原来用null表示一个值存不存在,现在用Optional来更好的表达这个概念,并且可以避免空指针异常
  • Optional类的JavaDoc描述为,这是一个可以为null的容器对象
    • 如果值存在
      • isPresent()方法返回true
      • get()方法,可以返回该对象

Api

创建Optional类对象的方法

  • Optional.of(T t):创建一个Optional实例,t必须非空,否则抛出空指针异常
  • Optional.empty():创建一个空的Optional实例
  • Optional.ofNullable(T t)t可以为空

判断Optional容器中是否包含对象

  • boolean isPresent():判断是否包含对象
  • void ifPresent(Consumer<? super T> consumer):如果有,就执行Consumer中接口方法accept()的实现代码,并且该值会作为参数传递给,即accept(值)

获取Optional容器中的对象

  • T get():如果调用对象包含值,返回该值,否则抛出异常
  • T orElse(T other):如果有值将其返回,否则返回指定的other对象
  • T orElseGet(Supplier<? extends T> other):如果有值将其返回,否则返回Supplier接口实现提供的对象
  • T orElseThrow(Supplier<? extends X> exceptionSupplier):如果有值则将其返回,否则抛出由Supplier接口实现提供的异常

举例说明Optional的使用

直观的写法

获取男孩的女朋友的名字

经典空指针判断
public static String getGirlName(Boy boy) {
if (boy != null) {
Girl girl = boy.getGirl();
if (girl != null)
return girl.getName();
}
}
return null;
}
info

使用Optional

使用Optional
public static String getGirlNameByOptional(Boy boy) {
// boy本身就可能是null,所以用ofNullable来创建Optional实例
Optional<Boy> optionalBoy = Optional.ofNullable(boy);
// boy不是空,就拿他女朋友; boy是空就给他一个空气女朋友
Boy resultBoy = optionalBoy.orElse(new Boy(new Girl("不存在的女生"), "备胎舔狗"));
// 还要判断:如果传进来的Boy不是空,那要看看他的女票是不是空的
Optional<Girl> optionalGirl = Optional.ofNullable(resultBoy.getGirl());
Girl resultGirl = optionalGirl.orElse(new Girl("不存在的女生"));
return resultGirl.getName();
}

另一种简洁写法

  • 经典
public static String getGirlName(Boy boy) {
if (boy == null) { // 男孩为空
return null;
}
if (boy.getGirl() == null) { // 男孩的女票为空
return null;
}
if (boy.getGirl().getName() == null) { // 男的女票的名字为空
return null;
}
return boy.getGirl().getName();
}
  • Optional
map和flatMap的区别
  • map会自动返回Optional类型

  • flatMap不会自动返回Optional类型,需要你自己确保返回的东西是Optional类型

public static String getGirlNameByOptional(Boy boy) {
String girlName = Optional.ofNullable(boy) // 实例化Optional
// 男孩不为空,拿他女票做Optional
.flatMap((Boy boy1) -> Optional.ofNullable(boy1.getGirl()))
// 女票不为空,那就拿女孩的名字做Optional
.map(Girl::getName).orElse("空气女朋友"); //男的、男的女朋友、女的名字 任意一个出现null值,就返回“空气女盆友”
return girlName;
}

测试

boy存在,但是他没女票 (null)

public static void main(String[] args) {
Boy boy = new Boy();
// boy = null;
// Boy boy = new Boy(new Girl(null), "王大锤");
// Boy boy = new Boy(new Girl("铃科百合子"), "王大锤");
String girlName = getGirlNameByOptional(boy);
System.out.println("girlName = " + girlName);
}
运行结果
girlName = 空气女朋友

boy不存在 (null)

public static void main(String[] args) {
Boy boy = new Boy();
boy = null;
// Boy boy = new Boy(new Girl(null), "王大锤");
// Boy boy = new Boy(new Girl("铃科百合子"), "王大锤");
String girlName = getGirlNameByOptional(boy);
System.out.println("girlName = " + girlName);
}
运行结果
girlName = 空气女朋友

boy存在,名叫王大锤,有个女票,但是不知道女票的名字 (null)

public static void main(String[] args) {
// Boy boy = new Boy();
// boy = null;
Boy boy = new Boy(new Girl(null), "王大锤");
// Boy boy = new Boy(new Girl("铃科百合子"), "王大锤");
String girlName = getGirlNameByOptional(boy);
System.out.println("girlName = " + girlName);
}
运行结果
girlName = 空气女朋友

boy存在,名叫王大锤,有个女票,名叫铃科百合子 (not null)

public static void main(String[] args) {
// Boy boy = new Boy();
// boy = null;
// Boy boy = new Boy(new Girl(null), "王大锤");
Boy boy = new Boy(new Girl("铃科百合子"), "王大锤");
String girlName = getGirlNameByOptional(boy);
System.out.println("girlName = " + girlName);
}
运行结果
girlName = 铃科百合子