Optional的作用是什么?
主要作用是消除空指针,但其本质就通过Optional来区分代码中那些内容是可以为空的,那些不可以为空。
我们平时的代码通过 xxx != null来判断某个对象不为空,所以我们常见的代码是这样的:
if(xxx !=null) {
xxx.get();
}
获取某个对象内部的值,需要先判断是否为空,如果没有判断就进行调用,那么很可能发生空指针NullPointerException。
而如果某个对象是可以为空的,那么使用Optional封装后,我们的代码就会比较流畅的编写,而不需要写过多的if判断,然后再获取其值。
比如人的名字肯定是不为空的,而人的汽车则是有的人有,有的人没有。
人和车这样定义:
@Data
public class OptPerson {
private String name;
private Optional<OptCar> optCar;
}
import lombok.Data;
@Data
public class OptCar {
private String carName;
private OptCarBrand optCarBrand;
}
import lombok.Data;
@Data
public class OptCarBrand {
private String brandName;
}
我们来看demo:
import java.util.Optional;
/**
* @author itzhimei
*/
public class OptionalEmpty {
public static void main(String[] args) {
//test1();
test2();
//test3();
}
public static void test1() {
OptPerson optPerson = new OptPerson();
optPerson.setName("IT之美");
optPerson.setOptCar(Optional.empty());
System.out.println(optPerson);
System.out.println(optPerson.getOptCar().get().getOptCarBrand());
}
/* 输出
OptPerson(name=IT之美, optCar=Optional.empty)
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at com.itzhimei.base.lambda.optional.OptionalEmpty.test1(OptionalEmpty.java:20)
at com.itzhimei.base.lambda.optional.OptionalEmpty.main(OptionalEmpty.java:11)
*/
public static void test2() {
OptPerson optPerson = new OptPerson();
optPerson.setName("IT之美");
optPerson.setOptCar(Optional.empty());
System.out.println(optPerson);
System.out.println("car为空:" + optPerson.getOptCar().orElse(new OptCar()).getOptCarBrand());
}
/* 输出
OptPerson(name=IT之美, optCar=Optional.empty)
car为空:null
*/
public static void test3() {
OptPerson optPerson = new OptPerson();
optPerson.setName("IT之美");
//optPerson.setOptCar(Optional.empty());
System.out.println(optPerson);
System.out.println(optPerson.getOptCar().get().getOptCarBrand());
System.out.println("car为空:" + optPerson.getOptCar().orElse(new OptCar()).getOptCarBrand());
}
/* 输出
OptPerson(name=IT之美, optCar=null)
Exception in thread "main" java.lang.NullPointerException
at com.itzhimei.base.lambda.optional.OptionalEmpty.test1(OptionalEmpty.java:20)
at com.itzhimei.base.lambda.optional.OptionalEmpty.main(OptionalEmpty.java:11)
*/
}
我们先看test1方法,这里面最重要的一行代码就是:optPerson.setOptCar(Optional.empty()),有了这一行代码,执行方法后还是报错,但是并不是空指针,这是因为Optional的get方法使用之前需要先调用isPresent()方法判断对象是否为空。
public static void test1() {
OptPerson optPerson = new OptPerson();
optPerson.setName("IT之美");
optPerson.setOptCar(Optional.empty());
System.out.println(optPerson);
System.out.println(optPerson.getOptCar().get().getOptCarBrand());
}
/* 输出
OptPerson(name=IT之美, optCar=Optional.empty)
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at com.itzhimei.base.lambda.optional.OptionalEmpty.test1(OptionalEmpty.java:20)
at com.itzhimei.base.lambda.optional.OptionalEmpty.main(OptionalEmpty.java:11)
*/
我们再看test2方法,test2方法获取汽车用的是optPerson.getOptCar().orElse(new OptCar()).getOptCarBrand(),我们可以看到代码并没有报错,输出的是null。
这里空竟然没有空指针,也没有报错,这就是Optional的强大之处,因为我们已经声明过car可以使empty,optPerson.setOptCar(Optional.empty()),所以在后续使用时,对empty的car调用,也不会产生空指针。
这就是我们在代码设计时,需要我们开发人员区分,哪些是可以为空的,可以为空的可以定义成Optional这样的类型,并在创建对象是将car声明为empty,那么后续调用,就变car是empty的,也不会产生空指针,从而减少了if判空的操作。
这是一种设计上的应用和选择。
我们先看test3方法, test3方法去掉了optPerson.setOptCar(Optional.empty())行代码,执行还是报了空指针,所以如果对象是null,直接调用null.xxx(),那么还是会空指针。