文章目录
1 Optional类
1.1 为什么引入Optional类
Java 8中引入了一个新的类java.util.Optional,其目的就是用于解决可能存在的空指针异常问题。举例来说,如果你知道一个人可能有也可能没有车,那么Person类内部的car变量就不应该声明为Car,遭遇某人没有车时把null引用赋值给它,而是应该直接将其声明为Optional类型。
- Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
- Optional是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
- Optional类的引入很好的解决空指针异常。
1.2 相关API
创建对象相关:
- Optional.empty():创建一个空的Optional实例。
- Optional.of(T t):创建一个Optional实例,当t为null时抛出异常(NullPointerException)。
- Optional.ofNullable(T t):创建一个Optional实例,但当t为null时不会抛出异常,而是返回一个空的实例。
获取对象相关:
-
get():获取optional实例中的对象,当optional容器为空时报错。
-
orElse(T other):如果optional不为空,则返回optional中的对象;如果为null,则返回other 这个默认值。
-
orElseGet(Supplier other):如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other。
-
orElseThrow(Supplier exception):如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常。
对象映射相关:
- map(Function<T, U> mapper):如果optional不为空,则将optional中的对象t映射成另外一个对象u,并将u存放到一个新的optional容器中。
- flatMap(Function<T,Optional > mapper):跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional。
- filter(Predicate p):filter()接受一个Predicate参数,返回测试结果为true的值。如果测试结果为false,会返回一个空的Optional。
判空相关:
- isPresent():判断optional是否为空,如果空则返回false,否则返回true。
- ifPresent(Consumer c):如果optional不为空,则将optional中的对象传给Comsumer函数。
2 API Demo
2.1 创建一个对象
@Data
@Accessors(chain = true)
public class Person {
private String name;
private Integer age;
private Optional<Car> cars;
@Data
@Accessors(chain = true)
public static class Car {
private String name;
}
}
2.2 测试创建对象相关API
@Slf4j
public class PersonTest1 {
@Test
public void testOf() {
Optional<Person> person1 = Optional.of(getPerson());
System.out.println("person1 = " + person1);
try {
Optional<Person> person2 = Optional.of(null);
System.out.println("person2 = " + person2);
} catch (NullPointerException e) {
log.error("of() 不支持传入null");
}
}
@Test
public void testOfNullable() {
Optional<Person> person1 = Optional.ofNullable(getPerson());
System.out.println("person1 = " + person1);
Optional<Person> person2 = Optional.ofNullable(null);
System.out.println("person2 = " + person2);
}
@Test
public void testEmpty() {
Optional<Person> person = Optional.empty();
try {
System.out.println("person = " + person.get());
} catch (NoSuchElementException e) {
log.error("NoSuchElementException");
}
}
private Person getPerson() {
return new Person().setName("Tom").setAge(18);
}
}
2.3 测试获取对象相关API
@Slf4j
public class PersonTest2 {
@Test
public void testOrElse() {
Person nullPer = null;
// 如果参数为null的话,就会执行并返回后面的函数
// 相当于提供一个默认值
Person person1 = Optional.ofNullable(nullPer).orElse(getSpecialPerson());
System.out.println("person1 = " + person1);
Person person2 = Optional.ofNullable(getPerson()).orElse(getSpecialPerson());
System.out.println("person2 = " + person2);
}
@Test
public void testOrElseGet() {
Person nullPer = null;
// 如果参数为null的话,就会执行并返回后面的函数
Person person1 = Optional.ofNullable(nullPer).orElseGet(this::getSpecialPerson);
System.out.println("person1 = " + person1);
Person person2 = Optional.ofNullable(getPerson()).orElseGet(this::getSpecialPerson);
System.out.println("person2 = " + person2);
}
@Test
public void testOrElseThrow() throws Exception {
Person nullPer = null;
try {
Person student = Optional.ofNullable(nullPer).orElseThrow(() -> new Exception("per is null"));
System.out.println(student);
} catch (Exception e) {
log.error("{}", e.getMessage());
}
}
private Person getPerson() {
return new Person().setName("Tom").setAge(18);
}
public Person getSpecialPerson() {
System.out.println("测试specialStudent是否被执行了");
return new Person().setName("Mary").setAge(22);
}
}
2.4 测试对象映射相关API
@Slf4j
public class PersonTest3 {
@Test
public void testMap() {
Person person = getPerson();
String name = Optional.of(person).map(Person::getName).get();
System.out.println("name = " + name);
}
@Test
public void testFlatMap() {
Person person = getPerson();
Optional<Person.Car> car = Optional.of(person).flatMap(Person::getCar);
System.out.println("car = " + car.get());
}
private Person getPerson() {
return new Person().setName("Tom").setAge(18).setCar(Optional.of(new Person.Car()));
}
}
2.5 测试判空相关API
@Slf4j
public class PersonTest4 {
@Test
public void version1() {
// 极其不优雅,多层嵌套if
Person student = getPerson();
if (student != null) {
doSomething1();
if (student.getName() != null) {
doSomething2(student.getName());
}
}
}
@Test
public void version2() {
// 和version1其实没有多大区别,推荐version3
Optional<Person> student = Optional.ofNullable(getPerson());
if (student.isPresent()) {
doSomething1();
if (student.get().getName() != null) {
doSomething2(student.get().getName());
}
}
}
@Test
public void version3() {
Optional<Person> student = Optional.ofNullable(getPerson());
student.ifPresent(stu -> {
doSomething1();
stu.getCar().ifPresent(car -> doSomething2(car.getName()));
});
}
private void doSomething1() {
log.info("do something");
}
private void doSomething2(String name) {
log.info("name: {}", name);
}
private Person getPerson() {
boolean b = new Random().nextBoolean();
if (b) {
Person.Car car = new Person.Car().setName("宝马");
return new Person().setName("Tom").setAge(18).setCar(Optional.of(car));
} else {
return null;
}
}
}
2.6 测试过滤API
@Slf4j
public class PersonTest5 {
@Test
public void testFilter() {
Optional<Person> opt = Optional.ofNullable(getPerson()).filter(stu -> stu.getName().startsWith("T"));
opt.ifPresent(stu -> {
log.info(stu.getName());
});
}
private Person getPerson() {
boolean b = new Random().nextBoolean();
if (b) {
Person.Car car = new Person.Car().setName("宝马");
return new Person().setName("Tom").setAge(18).setCar(Optional.of(car));
} else {
return null;
}
}
}