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

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

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

执行该测试方法

599f2bcba4a94974af5355fd4d17e0a2_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.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


相关文章
|
6月前
|
Java 编译器 程序员
【JavaSE专栏67】谈谈异常的那些事,学会预判异常、捕获异常、转移异常
【JavaSE专栏67】谈谈异常的那些事,学会预判异常、捕获异常、转移异常
【JavaSE专栏67】谈谈异常的那些事,学会预判异常、捕获异常、转移异常
|
5天前
|
Java
滚雪球学Java(17):探索循环控制:JavaSE中的break与continue秘技
【4月更文挑战第6天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
23 1
滚雪球学Java(17):探索循环控制:JavaSE中的break与continue秘技
|
1月前
,出现了一个RPA(机器人流程自动化)的运行异常,具体错误为 `rpa.core.errors.RPATimeoutError`
【2月更文挑战第21天】,出现了一个RPA(机器人流程自动化)的运行异常,具体错误为 `rpa.core.errors.RPATimeoutError`
33 2
|
3月前
|
安全 Java 程序员
Dating Java8系列之巧用Optional之优雅规避NPE问题
Dating Java8系列之巧用Optional之优雅规避NPE问题
21 0
|
Java 开发者 容器
【Java挠头】Java异常、捕获、处理、throw、throws等绝妙剖析
【Java挠头】Java异常、捕获、处理、throw、throws等绝妙剖析
126 0
【Java挠头】Java异常、捕获、处理、throw、throws等绝妙剖析
|
Java 数据库连接
你有没有掉进去过这些 Exception 的“陷阱“(Part C)
你有没有掉进去过这些 Exception 的“陷阱“(Part C)
你有没有掉进去过这些 Exception 的“陷阱“(Part C)
你有没有掉进去过这些 Exception 的“陷阱”(Part A)
你有没有掉进去过这些 Exception 的“陷阱”(Part A)
你有没有掉进去过这些 Exception 的“陷阱”(Part A)
|
Java
再也不要对java中==和equals的区别有困惑了,这篇文章保证你能懂
想到你应该无数次看到过这个问题了,也可能你已经看过无数篇文章了,如果你还是一头雾水或者是不理解,那试着看看这篇文章,相信你一定能看懂。
93 0
再也不要对java中==和equals的区别有困惑了,这篇文章保证你能懂
|
Java
Continue与Break在使用过程中的爱恨情仇| Java Debug 笔记
Continue与Break在使用过程中的爱恨情仇| Java Debug 笔记
82 0