五、Optional
Java 8 中引入Optional,可以更优雅的处理空指针异常,用来表示一个变量的值可以为空也可以不为空,官方描述说引入Optional并不是要消除每一个null引用,他的目标是帮助更好的设计出朴实的API,通过方法名就能了解它是否接受一个Optional值。
Optional
- 是什么:是一个容器
- 含义:代表存在与不存在
- 作用:规避空指针异常
- 可以看作是包含一个元素的集合
- 不能作为类的属性使用,没有实现序列化接口
- 在领域模型应用中小心使用
Optional是一个容器类,用来保存泛型传递的值,代表一个值存在或者不存在,在Java8之前使用NULL表示一个值不存在,Optional也可以表示值不存在,并且可以规避空指针异常。Optional中的常用方法
// 将指定的值,用Optional封装之后返回,如果值为null会抛出空指针异常 Optional<T> of(T value) // 用于创建空的Optional实例,既Option容器实例中不包含任何元素 Optional<T> empty() // 将指定的值,用Optional封装之后返回,如果传入的值为null,会返回一个空的Option容器 Optional<T> ofNullable(T value) // 如果value值存在就返回value,否则抛出异常 T get() 复制代码
Optional判断的使用
新建一个OptionalTest测试类,增加testIsUserEqualNullByOptional()测试方法
public class OptionalTest { @Test public void testIsUserEqualNullByOptional(){ Optional<User> optionalUser = Optional.empty(); // 判断Optional是否为空 if (optionalUser.isPresent()){ System.out.println("user非空"); } else { System.out.println("user为空"); } } } 复制代码
执行该测试方法
这种判断方式与直接判断是否为null几乎没有任何区别
orElse()、orElseGet()、orElseThrow()、map() 方法的使用
orElse(),返回Optional中存在的值,不存在提供默认值
在OptionalTest测试类中新增测试方法
@Test public void testOptionalOrElse(){ // User user = null; User user = new User(); user.setName("stark"); Optional<User> optionalUser = Optional.ofNullable(user); // 存在既返回,为空则提供默认值 User user1 = optionalUser.orElse(new User()); System.out.println(user1); } 复制代码
user不为空时,返回了user对象
user为空时返回了new出来的一个user对象,属性都为空
orElseGet(),返回Optional中存在的值,不存在通过函数创建
在OptionalTest测试类增加测试方法
private static User create(){ User user = new User(); user.setName("这是通过函数创建的User对象"); return user; } @Test public void testOptionalOrElseGet(){ // User user = null; User user = new User(); user.setName("stark"); Optional<User> optionalUser = Optional.ofNullable(user); // 存在既返回,为空则通过函数创建,更灵活 User user1 = optionalUser.orElseGet(() -> create()); System.out.println(user1); } 复制代码
User对象不为空时,直接返回User对象
User对象为空时,通过函数创建出User对象
orElseThrow(),返回Optional中存在的值,不存在则抛出异常
在OptionalTest测试类新增方法
@Test public void testOptionalOrElseThrow(){ // User user = null; User user = new User(); user.setName("stark"); Optional<User> optionalUser = Optional.ofNullable(user); // 存在既返回,不存在抛出异常 User user1 = optionalUser.orElseThrow(RuntimeException::new); System.out.println(user1); } 复制代码
User对象不为null时直接返回User对象
User对象为空时抛出异常
ifPresent(),对Optional中存在的值进行处理,不存在则不做任何处理
OptionalTest测试类
@Test public void testOptionalIfPresent(){ // User user = null; User user = new User(); user.setName("stark"); Optional<User> optionalUser = Optional.ofNullable(user); // 存在打印出name,不存在不做任何处理 optionalUser.ifPresent(user1 -> System.out.println(user1.getName())); } 复制代码
User不为空时打印出User对象的name属性
User对象为空时,不做任何处理,规避了空指针异常的问题
map(),对Optional中的值进行处理,返回Optional对象
在OptionalTest测试类新增测试方法
@Test public void testOptionalMap(){ // User user = null; User user = new User(); user.setName("stark"); Optional<User> optionalUser = Optional.ofNullable(user); // map可以对Optional中的对象执行某个操作,并且会返回Optional对象,因此可以执行级联操作 String u = optionalUser.map(user1 -> user1.getName()).orElse("user为空时返回的值"); System.out.println(u); } 复制代码
User对象不为空时返回User对象的name属性的值
User对象为空时返回指定的字符串
由于map()方法返回一个Optional对象,因此可以进行级联操作
@Test public void testOptionalMapCascade(){ // User user = null; User user = new User(); user.setName("stark"); Optional<User> optionalUser = Optional.ofNullable(user); // map级联操作 Integer len = optionalUser.map(u -> u.getName()).map(name -> name.length()).orElse(0); System.out.println(len); } 复制代码
User对象不为空时先获取对象的name属性值,接着获取name属性值的长度
User对象为空时,直接输出长度为0,规避了空指针异常的问题