你有没有掉进去过这些 Exception 的“陷阱“(Part B)

981 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情

五、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为空");
        }
    }
}

执行该测试方法 image.png

这种判断方式与直接判断是否为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对象 image.png

user为空时返回了new出来的一个user对象,属性都为空 image.png

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对象 image.png

User对象为空时,通过函数创建出User对象 image.png

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对象 image.png

User对象为空时抛出异常 image.png

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属性 image.png

User对象为空时,不做任何处理,规避了空指针异常的问题 image.png

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属性的值 image.png

User对象为空时返回指定的字符串 image.png

由于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属性值的长度 image.png

User对象为空时,直接输出长度为0,规避了空指针异常的问题 image.png