炫技亮点 使用Optional类优化代码,提升可读性和简化空值处理

这篇具有很好参考价值的文章主要介绍了炫技亮点 使用Optional类优化代码,提升可读性和简化空值处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

在日常的软件开发中,我们经常需要处理可能为空的值,例如从数据库查询数据调用外部接口获取数据从配置文件读取配置项等。传统的处理方式往往需要使用繁琐的空值判断和异常处理代码,使得代码变得冗长和难以理解。为了解决这个问题,Java 8 引入了 Optional 类,它提供了一种优雅和简洁的方式来处理可能为空的值,提升代码的可读性和简化空值处理。

Optional 简介

Optional 是 Java 8 中引入的一个类,它的主要目的是解决空值处理的问题。Optional 可以包装一个值,这个值可以是 null,也可以是非 null。通过使用 Optional,我们可以避免显式的空值判断,从而简化代码逻辑。

Optional类有两种状态:

  • 存在值的状态,表示对象不为空。
  • 空值状态,表示对象为空。

优化代码示例

让我们从一个简单的示例开始,假设我们有一个 User 类,其中包含一个可能为 null 的 name 属性。我们希望获取该用户的名字,并在名字存在时打印出来。下面是一个未优化的代码示例:

User user = getUser();
if (user != null) {
    String name = user.getName();
    if (name != null) {
        System.out.println("User name: " + name);
    }
}

在这个示例中,我们使用了多层的 null 检查来避免空指针异常。代码看起来冗长而且不易读,可读性差,难以理解。

现在,让我们使用 Optional 来优化这段代码:

Optional<User> optionalUser = Optional.ofNullable(getUser());
optionalUser.map(User::getName)
            .ifPresent(name -> System.out.println("User name: " + name));

通过使用 Optional,我们可以将 null 检查和操作合并到一起,使代码更加简洁和易读。

  • 首先,我们使用 Optional.ofNullable 方法来创建一个 Optional 对象,它可以包含一个可能为 null 的值。
  • 然后,我们使用 map 方法来从 Optional 对象中获取用户的名字。最后,我们使用 ifPresent 方法来在名字存在时执行打印操作。

更复杂点儿的示例如下:

// 传统方式
if (user != null) {
    if (user.getAge() != null) {
        int age = user.getAge();
        System.out.println("User age: " + age);
    } else {
        System.out.println("Age not available");
    }
} else {
    System.out.println("User not found");
}
// 使用 Optional
Optional<User> userOptional = Optional.ofNullable(user);
userOptional.map(User::getAge)
        .ifPresent(age -> System.out.println("User age: " + age))
        .orElse(() -> System.out.println("Age not available"))
        .orElse(() -> System.out.println("User not found"));

常见的Optional方法

  1. 创建Optional对象

    • Optional.of(value): 创建一个包含指定值的Optional对象。如果传入的值为null,会抛出NullPointerException。
    • Optional.ofNullable(value): 创建一个包含指定值的Optional对象,允许传入null值。
    • Optional.empty(): 创建一个空的Optional对象,表示值不存在。
  2. 判断Optional是否包含值

    • isPresent(): 判断Optional对象是否包含值,如果有值返回true,否则返回false。
  3. 获取Optional中的值

    • get(): 获取Optional对象中的值。如果Optional对象为空,会抛出NoSuchElementException异常。建议在调用get()方法之前先使用isPresent()方法进行判断。
  4. 处理Optional对象的值

    • ifPresent(Consumer<? super T> consumer): 如果Optional对象包含值,执行指定的操作。传入的参数是一个Consumer函数接口,用于处理Optional中的值。
  5. 处理Optional对象的值,如果值不存在执行指定的逻辑

    • orElse(T other): 如果Optional对象包含值,返回该值,否则返回指定的默认值。
    • orElseGet(Supplier<? extends T> supplier): 如果Optional对象包含值,返回该值,否则通过Supplier函数接口生成一个默认值并返回。
    • orElseThrow(Supplier<? extends X> exceptionSupplier): 如果Optional对象包含值,返回该值,否则通过Supplier函数接口生成一个异常并抛出。
  6. 对Optional对象的值进行转换

    • map(Function<? super T, ? extends U> mapper): 如果Optional对象包含值,对该值进行转换并返回一个新的Optional对象。
    • flatMap(Function<? super T, Optional<U>> mapper): 如果Optional对象包含值,对该值进行转换并返回一个新的Optional对象。与map不同的是,flatMap方法的转换结果必须是一个Optional对象。
  7. 过滤Optional对象的值

    • filter(Predicate<? super T> predicate): 如果Optional对象包含值,并且该值满足指定的条件,返回包含该值的Optional对象,否则返回一个空的Optional对象。

使用示例

1. 不为空值处理

// 1.无返回值 ifPresent
// 传统方式
if (user.isPresent()) {
  System.out.println(user.get());
}
// 优化后
user.ifPresent(System.out::println);

// 2.有返回值 map
// 传统方式
User user = .....
if(user != null) {
  String name = user.getUsername();
  if(name != null) {
    return name.toUpperCase();
  } else {
    return null;
  }
} else {
  return null;
}
// 优化后
user.map(u -> u.getUsername())
    .map(name -> name.toUpperCase())
    .orElse(null);

2. 为空值处理

// 1.为空返回默认值 orElse("Unknown")
// 传统方式
User user = getUser();
if (user != null) {
    String name = user.getName();
   if(name != null) {
       return name;
   } else {
    return "Unknown";
   } 
} else {
  return "Unknown";
}    
// 优化后    
Optional<User> optionalUser = Optional.ofNullable(getUser());
String name = optionalUser.map(User::getName)
                         .orElse("Unknown");
// 2.为空抛出指定异常 orElseThrow()
// 传统方式
public String getUserName(long userId) {
    User user = userRepository.findById(userId);
    if (user != null) {
        return user.getName();
    } else {
        throw new UserNotFoundException("User not found");
    }
}
// 优化后
public String getUserName(long userId) {
    Optional<User> userOptional = userRepository.findById(userId);
    return userOptional.map(User::getName).orElseThrow(() -> new UserNotFoundException("User not found"));
}

3. 避免空指针异常

当我们访问一个对象的属性或调用其方法时,经常需要进行空指针检查,以避免出现 NullPointerException。使用 Optional 可以简化这种检查,使得代码更加简洁和安全。

Optional<String> name = Optional.ofNullable(user.getName());
String result = name.orElse("Unknown");

在上述示例中,我们使用 Optional.ofNullable 方法来创建一个 Optional 对象,并通过 orElse 方法设置一个默认值,以防止 name 为空时出现 NullPointerException。

4. 级联操作

Optional<User> optionalUser = Optional.ofNullable(getUser());
Optional<String> optionalEmail = optionalUser.map(User::getEmail);
Optional<String> optionalDomain = optionalEmail.flatMap(this::extractDomain);

在这个示例中,我们使用 mapflatMap 方法来对多个 Optional 进行级联操作,从而避免了多层的 null 检查。

5. 过滤操作

Optional<User> optionalUser = Optional.ofNullable(getUser());
Optional<User> filteredUser = optionalUser.filter(user -> user.getAge() >= 18);

在这个示例中,我们使用 filter 方法来过滤符合条件的用户,只保留年龄大于等于 18 岁的用户。

6. 链式调用

Optional 提供了一系列的操作方法,可以进行链式调用,使得代码更加流畅和易读。

String email = userRepository.findById(userId)
        .flatMap(user -> user.getEmail())
        .orElse("No email found");

在上述示例中,我们通过链式调用的方式,先从 UserRepository 中根据用户ID查询用户对象,然后通过 flatMap 方法获取用户的邮箱。如果邮箱为空,我们使用 orElse 方法设置一个默认值。

7. 复杂场景结合stream api

假设我们有一个 Order 类,它包含一个 items 属性,代表订单中的商品列表。我们需要计算订单的总金额。

传统方式是通过判断订单是否为空以及商品列表是否为空来进行处理:

public BigDecimal calculateTotalAmount(Order order) {
    if (order != null && order.getItems() != null) {
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (OrderItem item : order.getItems()) {
            totalAmount = totalAmount.add(item.getPrice());
        }
        return totalAmount;
    } else {
        return BigDecimal.ZERO;
    }
}

Optional优化后

public BigDecimal calculateTotalAmount(Order order) {
    return Optional.ofNullable(order)
            .map(Order::getItems)
            .orElse(Collections.emptyList())
            .stream()
            .map(OrderItem::getPrice)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
}

在上述示例中,我们通过调用 Optional.ofNullable(order) 方法获取一个 Optional 对象,然后使用 map() 方法获取订单的商品列表。如果订单或商品列表为空,我们使用 orElse(Collections.emptyList()) 方法返回一个空的列表。然后,我们使用流式编程的方式计算商品价格的总和。文章来源地址https://www.toymoban.com/news/detail-548167.html

到了这里,关于炫技亮点 使用Optional类优化代码,提升可读性和简化空值处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 编写魅力十足的代码:优化可读性、维护性和性能的关键

    本篇汇总了平时在工作开发中常遇到的业务逻辑的优雅写法,也汇总了自己还是新人时,拿到一个业务不知道怎么下手的痛点,依稀记得那时候总感觉自己写的代码不规范。 写完之后,感觉还是美好的,又学到东西了。 采用简洁的语法和结构,遵循一致的命名规范,具有良

    2024年02月10日
    浏览(46)
  • 【Spring MVC】获取 @RequsetBody 标识的对象,使用适配器模式增加代码可读性

    一个技术需求引发的思考和实践: 思考 用 AOP 把校验代码 实践 用 Spring MVC 的 RequestBodyAdvice 做AOP逻辑 继承 RequestBodyAdviceAdapter 实现自己的 适配器 用自己的适配器让代码可读性增加 熟悉 Spring MVC 、Java 反射的一些实践 本文内容 澄清一个AOP校验JSON内容的思路 复习适配器模式

    2024年02月10日
    浏览(30)
  • 【深入浅出系列】之代码可读性

    这是“深入浅出系列”文章的第一篇,主要记录和分享程序设计的一些思想和方法论,如果读者觉得所有受用,还请“一键三连”,这是对我最大的鼓励。 一句话:见名知其义。有人说好的代码必然有清晰完整的注释,我不否认;也有人说代码即注释,是代码简洁之道的最高

    2024年02月11日
    浏览(32)
  • 算法——让你的代码更具有可读性

    今天其实算一个小专栏(内容参考《代码大全2》)明天开始更新具体的算法,这些算法我都会从力扣上找,语言的话暂时是c和c++还有c#的写法(不要过于专注于编程语言,语言只是工具,关键在于学习思维) 我们创建子程序的目的,就是让主函数尽量简洁,复杂的部分放到

    2024年01月20日
    浏览(50)
  • 如何编写可读性高的 C 代码?

    目录 1.引言 2.基础知识 3.面向对象语言的特性 4.C 语言的面向对象 5.测试 6.总结         面向对象的语言更接近人的思维方式,而且在很大程度上降低了代码的复杂性,同时提高了代码的可读性和可维护性,传统的 C 代码同样可以设计出比较易读,易维护,复杂度较低的优

    2024年04月22日
    浏览(26)
  • 《程序员的炫技代码》

      程序员,这个职业总是让人感到神秘而又充满魅力。他们手中的代码常常充满了令人惊叹的炫技操作,让人不禁感叹他们的技术能力之高。在这篇文章中,我想和大家分享一些我所知道的程序员的炫技代码。 一行代码实现斐波那契数列 斐波那契数列是一组数列,其中每个

    2024年02月06日
    浏览(39)
  • 代码可读性艺术在Andorid中的体现

    前言 最近接手的一些项目,不同的人编码风格迥异,类里的变量、方法的定义穿插,注释极为稀少,更有一些变量和方法的命名非常近似,例如表示播放队列的\\\"playQueue\\\"和表示歌单的\\\"playList\\\",wtf? 这不是一个意思吗?一些回调的时机也不能直观的看出来,通常需要debug调试多次;multi proj

    2024年02月03日
    浏览(26)
  • 程序员的炫技代码写法

    程序员,这个职业总是让人感到神秘而又充满魅力。他们手中的代码常常充满了令人惊叹的炫技操作,让人不禁感叹他们的技术能力之高。在这篇博客中,我想和大家分享一些我所知道的程序员的炫技代码写法。 一、代码美感——灵动转换 美感是良好的编码风格的基础,也

    2024年02月08日
    浏览(52)
  • 提高代码可读性和可维护性的命名建议

    当进行接口自动化测试时,良好的命名可以提高代码的可读性和可维护性。以下是一些常用的命名建议: 变量和函数命名: 使用具有描述性的名称,清晰地表达变量或函数的用途和含义。 使用小写字母和下划线来分隔单词,例如  login_url 、 send_request 。 避免使用单个字符或

    2024年02月10日
    浏览(32)
  • 50个简洁的提示提高代码可读性和效率(0-10)

    这篇文章整理了50个简洁的提示,可以提高您的代码可读性和效率。这些提示来自个人项目、彻底的代码审查和与资深开发人员的启发性讨论。 无论您是新手还是经验丰富的开发人员,这篇文章都应该能够帮助您学到一些东西。 这个列表包括常见的Python模式、核心概念和最佳

    2024年02月10日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包