详解 JDK8 新特性之 Optional 类
目标
- 回顾以前对 null 的处理方式
- 介绍 Optional 类
- 掌握 Optional 的基本使用
- 掌握 Optional 的高级使用
以前对 null 的处理方式
public class Test01 {
public static void main(String[] args) {
String name = null;
if (name != null) {
System.out.println("姓名为:" + name);
} else {
System.out.println("姓名不存在");
}
}
}
Optional 类介绍
Optional是一个没有子类的工具类,Optional 是一个可以为 null 的容器对象。它的作用主要就是为了解决避免 Null检查,防止 NullPointException。
Optional类的创建方式:
Optional.of(T t):创建一个 Optional 实例
Optional.empty():创建一个空的 Optional 实例
Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
Optional 类的常用方法
isPresent():判断是否包含值,包含值返回true,不包含值返回false
get():如果Optional有值则将其返回,否则抛出NoSuchElementException
orElse(T t):如果调用对象包含值,返回该值,否则返回参数t
orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f):如果有值对其处理,并返回处理后的 Optional,否则返回 Optional.empty()
filter(Predicate<? super T> predicate)
flatMap(Function<? super T, Optional<U>> mapper)
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
Optional类的基本使用
public class Test02 {
public static void main(String[] args) {
// 1、创建Optional对象
// of 只能传入一个具体值,不能传入 null
Optional<String> op1 = Optional.of("凤姐");
// Optional<String> op1 = Optional.of(null);
// ofNullable 既可以传入具体值,也可以传入 null
// Optional<String> op2 = Optional.ofNullable("如花");
// Optional<Object> op2 = Optional.ofNullable(null);
// empty 存入的是空
Optional<Object> op3 = Optional.empty();
// 2、isPresent 判断Optional是否有具体值,有值返回true,没有值返回false
// boolean present = op1.isPresent();
// System.out.println("present = " + present);
// 3、get 获取Optional中的值,如果有值就返回值具体值,没有值就报错 NoSuchElementException
// System.out.println(op1.get());
// System.out.println(op3.get());
// 一般 isPresent 和 get 配合使用
if (op1.isPresent()) {
System.out.println(op1.get());
} else {
System.out.println("没有值");
}
}
}
Optional的高级使用:
package optional;
import java.util.Objects;
import java.util.Optional;
public class Test03 {
public static void main(String[] args) {
// extracted();
// extracted2();
extracted3();
}
private static void extracted3() {
User user = new User(null, 18);
System.out.println(getUpperUserName1(user));
Optional<User> op = Optional.ofNullable(user);
System.out.println(getUpperUserName2(op));
}
// 定义一个方法将 user 中的用户名转成大写并返回
// 使用Optional方式
public static String getUpperUserName2(Optional<User> op) {
String upperName = op.map(User::getUserName)
.map(String::toUpperCase)
.orElse(null);
return upperName;
}
// 定义一个方法将 user 中的用户名转成大写并返回
// 使用传统方式
public static String getUpperUserName1(User u) {
if (u != null) {
String userName = u.getUserName();
if (userName != null) {
return userName.toUpperCase();
} else {
return null;
}
} else {
return null;
}
}
private static void extracted2() {
Optional<String> userName = Optional.of("凤姐");
// Optional<String> userName = Optional.empty();
// 存在做什么
// ifPresent 如果有值就调用参数,没有值啥都不干
/*userName.ifPresent(s -> {
System.out.println("有值:" + s);
});*/
// 存在做点什么,不存在做点什么 我的jdk8没有这个方法
/*userName.ifPresentOrElse(s -> {
System.out.println("有值:" + s);
}, () -> {
System.out.println("没有值");
});*/
}
private static void extracted() {
// Optional<String> userName = Optional.of("凤姐");
Optional<String> userName = Optional.empty();
// orElse 如果Optional有值,就取出这个值,如果没有值就使用参数指定的值
String name = userName.orElse("如花吗?");
System.out.println("name = " + name);
}
}
class User {
private String userName;
private Integer age;
public User() {
}
public User(String userName, Integer age) {
this.userName = userName;
this.age = age;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(userName, user.userName) && Objects.equals(age, user.age);
}
@Override
public int hashCode() {
return Objects.hash(userName, age);
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
}
小结
Optional 是一个可以为 null 的容器对象。orElse,ifPresent,ifPresentOrElse,map等方法避免对 null 的判断,写出更优雅的代码。