你有没有掉进去过这些 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


相关文章
|
SQL 分布式计算 Java
IDEA 打包 Spark 项目 POM 文件依赖
这是一个 Maven POM 示例,用于构建一个使用 Spark 与 Hive 的项目,目标是将数据从 Hive 导入 ClickHouse。POM 文件设置了 Scala 和 Spark 的依赖,包括 `spark-core_2.12`, `spark-sql_2.12`, 和 `spark-hive_2.12`。`maven-assembly-plugin` 插件用于打包,生成包含依赖的和不含依赖的两种 JAR 包。`scope` 说明了依赖的使用范围,如 `compile`(默认),`provided`,`runtime`,`test` 和 `system`。
386 0
|
Oracle 关系型数据库 数据库
Oracle启动和停止的方式详解
Oracle启动和停止的方式详解
398 0
|
负载均衡 监控 定位技术
分库表数据倾斜的处理让我联想到了 AKF 模型
这里的特殊性可以是表中字段的某一个属性,比如订单编号、创建时间等等。这就需要我们根据实际情况,既要拆分的均匀又要拆分之后能满足未来几年的发展,同时还要满足现有业务的支持。
368 0
|
SQL Serverless 数据库
【count(列名)、count(1)和 count(星号)有什么区别】
【count(列名)、count(1)和 count(星号)有什么区别】
431 0
|
SQL Java 数据库
Spring Boot 学习研究笔记(九) - Spring Data JPA常用注解(1)
Spring Boot 学习研究笔记(九) - Spring Data JPA常用注解
410 0
|
存储 Cloud Native Java
Linux下systemd深入指南:如何优化Java服务管理与开机自启配置
Linux下systemd深入指南:如何优化Java服务管理与开机自启配置
651 0
|
SQL 消息中间件 Java
百万级数据excel导出功能如何实现?
这个功能挺有意思的,里面需要注意的细节还真不少,现在拿出来跟大家分享一下,希望对你会有所帮助。 原始需求:用户在UI界面上点击全部导出按钮,就能导出所有商品数据。
771 0
百万级数据excel导出功能如何实现?
|
JavaScript
textarea 动态宽高(根据内容动态撑开宽高)
textarea 动态宽高(根据内容动态撑开宽高)
649 0
|
SQL Java 关系型数据库
Spring Boot常用数据库开发技术总结:JDBCTemplate、JPA、Mybatis
1.概述 数据库开发一直是JAVA开发的核心之一,作为现在JAVA EE的基石框架,Spring Boot自身携带了一个JDBCTemplate框架,其对JDBC进行了基础的封装,使得Spring Boot原生就支持据库开发。同时Spring Boot也不排斥其它优秀的持久层框架,允许他们以极低的代价平滑的接入。 本文主要介绍最常用到的三个持久层框架,JdbcTemplate、JPA、mybatis如何接入Spring Boot并在其上进行开发。
538 0
|
JavaScript 小程序 Oracle
Sharding JDBC 实战:分布式事务处理
Sharding JDBC 实战:分布式事务处理