Optional类的使用
JDK8以前,编写代码,通常出现空指针异常的情况下,都是通过 if … else… 来对对象进行为空判断,然后再进行逻辑处理,代码写起来也比较冗余。
JDK8新增了Optional类,使用该类可以避免对空指针的检查,使代码看起来比较优雅。
1.Optional类介绍
JDK8新增了Optional 类,它是一个没有子类的工具类。我们可以把它看作是一个容器。这个容器有两种情况:①要么有值 ②要么为null。
2. 创建 Optional 类对象的方式
//1.创建一个Optional实例
Optional.of(T t);
//2.创建一个空的Optional实例
Optional.empty();
//3.若t不为null,创建Optional实例,否则创建空实例
Optional.ofNullable(T t);
public static void main(String[] args) {
//1.1 该方法只能传入一个具体值,不能传入null,否则报空指针异常
Optional<String> op1 = Optional.of("China");
log.info("op1:{}", op1);
//1.2 该方法可以传入具体值,也可以传入null,并不会报空指针异常
Optional<String> op2 = Optional.ofNullable(null);
log.info("op2:{}", op2);
//1.3 该方法创建一个空 Optional,存入的是null
Optional<Object> op3 = Optional.empty();
log.info("op3:{}", op3);
}
3.Optional 类常用方法
3.1.isPresent()
判断是否包含值。包含值返回 true,不包含值返回 false
public static void main(String[] args) {
Optional<String> optional = Optional.of("China");
boolean isPresent = optional.isPresent();
log.info("isPresent是否包含值:{}", isPresent);//true
Optional<String> emptyOpt = Optional.empty();
boolean emptyPresent = emptyOpt.isPresent();
log.info("emptyPresent是否包含值:{}", emptyPresent);//false
}
3.2.get()
如果Optional有值则将其返回,否则抛出 NoSuchElementException: No value present 异常
public static void main(String[] args) {
Optional<String> optional = Optional.of("China");
String key1 = optional.get();
log.info("获取key1值:{}", key1);
Optional<String> emptyOpt = Optional.empty();
String key2 = emptyOpt.get();
log.info("获取key2值:{}", key2);//NoSuchElementException
}
3.3.orElse()
如果调用对象包含值,返回该值,否则返回参数字符串str
public static void main(String[] args) {
Optional<String> optional = Optional.of("China");
String key1 = optional.orElse("为空");
log.info("获取key1值:{}", key1); //China
Optional<String> emptyOpt = Optional.empty();
String key2 = emptyOpt.orElse("为空");
log.info("获取key2值:{}", key2); //为空
}
3.4.orElseGet()
如果调用对象包含值,返回该值。否则返回 s 获取的值
public static void main(String[] args) {
//同orElse()类似,只是传参数类型不同,orElse()为String类型,orElseGet()为lambda
Optional<String> optional = Optional.of("China");
String key1 = optional.orElseGet(() -> "aaa");
log.info("获取key1值:{}", key1); //China
Optional<String> emptyOpt = Optional.empty();
String key2 = emptyOpt.orElseGet(() -> "aaa");
log.info("获取key2值:{}", key2); //aaa
}
3.5.orElseThrows()
如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
public static void main(String[] args) {
//同orElse()类似,只是传参数类型不同,orElse()为String类型,orElseGet()为lambda
Optional<String> optional = Optional.of("China");
String key1 = optional.orElseThrow(() -> new NullPointerException("为空"));
log.info("获取key1值:{}", key1); //China
Optional<String> emptyOpt = Optional.empty();
String key2 = emptyOpt.orElseThrow(() -> new NullPointerException("为空"));
log.info("获取key2值:{}", key2); //为空
}
3.6.map()
如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
public static void main(String[] args) {
//与 Stream 流 map()方法类似,可用于类型转换等操作
User user = new User("001", "小明");
Optional<User> optUser = Optional.of(user);
log.info("user:{}", optUser.get());
Optional<String> s = optUser.map(p -> p.getUserName());
log.info("s:{}", s.get()); //小明
}
3.7.flatMap()
如果有值,为其执行 mapping 函数返回 Optional 类型返回值,否则返回空Optional。
flatMap() 与 map()方法类似,区别在于 mapping 函数的返回值不同。map() 方法的 mapping 函数返回值可以是任何类型T,在 map () 方法返回之前会包装为 Optional。而 flatMap() 方法的 mapping函数必须是 Optional。调用结束时,flatMap不会对结果用Optional封装。
public static void main(String[] args) {
User user = new User("001", "小明");
Optional<User> optUser = Optional.ofNullable(user);
Optional<String> s = optUser.map(p -> p.getUserName());
log.info("s:{}", s.get()); //小明
Optional<String> m = optUser.flatMap(p -> Optional.of(p.getUserName()));
log.info("m:{}", m.get()); //小明
}
3.8.filter()
filter()方法通过传入限定条件对 Optional 实例的值进行过滤。如果有值并且满足
Predicate判断条件,则返回包含该值的Optional,否则返回空 Optional
public static void main(String[] args) {
Optional<String> opt1 = Optional.of("China");
String key1 = opt1.filter(s -> s.length() > 4).orElseThrow(() ->
new RuntimeException(("长度大于4")));
log.info("key1:{}", key1); //China
Optional<String> opt2 = Optional.of("China");
String key2 = opt2.filter(s -> s.length() > 5).orElse(("长度大于5"));
log.info("key2:{}", key2); //长度大于5
}
3.9.ifPresent()
如果值存在则使用该值调用consumer,否则不做任何事情
public static void main(String[] args) {
Optional<String> opt1 = Optional.of("China");
opt1.ifPresent((str)-> log.info("str:{}", str.toLowerCase()));//China
Optional<String> emptyOpt = Optional.empty();
emptyOpt.ifPresent((str)-> log.info("str:{}", str.toLowerCase()));//不返回内容
}
3.10.ifPresentOrElse()
JDK9以后提供。如果值存在则使用该值调用consumer,否则执行自定义的 Runnalbe 操作
public static void main(String[] args) {
Optional<String> optional = Optional.of("China");
optional.ifPresentOrElse((str)-> System.out.println(str.toLowerCase()),
()-> System.out.println("str为空"));//China
Optional<String> emptyOpt = Optional.empty();
emptyOpt.ifPresentOrElse((str)-> System.out.println(str.toLowerCase()),
()-> System.out.println("str为空"));//str为空
}
3.11.equals()
判断其他对象是否等于Optional
public static void main(String[] args) {
Optional<String> opt1 = Optional.of("China");
Optional<String> opt2 = Optional.of("China");
boolean flag = opt1.equals(opt2);
log.info("flag:{}", flag); //true
}