Java Optional学习笔记

目录

前言

一、Optional 的用途

二、Optional 的创建

 三、Optional 的常用方法

四、Optional优化案例

五、Optional的使用建议 

六、总结


前言

学习了b站up主AlbertShen的视频,受益匪浅,写下这篇笔记,地址:Java-Optional视频

一、Optional 的用途

在 Java 编程中,null值常常带来 NullPointerException 的风险,使得代码充斥着冗长的 null 检查语句,降低了代码可读性和可维护性。为了解决这个问题,Java 8 引入了 Optional 类,其主要用途如下:

  • 解决空指针异常: Optional 类就像一个容器,可以包含值或为空。通过提供一系列操作方法,可以方便地操作内部的值,避免直接访问可能为空的对象,从而有效防止空指针异常。

  • 提高代码可读性: 使用 Optional 可以清晰地表达返回值可能为空的情况,使代码更加易于理解和维护。

  • 支持函数式编程: Optional 的设计也考虑了函数式编程的原则,可以与 Lambda 表达式和 Stream API 等特性结合使用,实现更优雅的链式调用。

二、Optional 的创建

Optional.empty(): 创建一个空的 Optional 对象,表示没有值。

Optional<Object> optionalBox = Optional.empty();
System.out.println(optionalBox.isPresent()); // 输出: false
System.out.println(optionalBox.isEmpty());  // 输出: true

Optional.of(value): 创建一个包含非空值的 Optional 对象。如果传入的值为 null,则会抛出 NullPointerException。

String value = "maike";
Optional<String> optionalBox = Optional.of(value);
System.out.println(optionalBox.isPresent()); // 输出: true
System.out.println(optionalBox.isEmpty());  // 输出: false

Optional.ofNullable(value): 创建一个 Optional 对象,可以包含值或为空,适用于处理不确定是否为空的情况。

String value = null;
Optional<String> optionalBox = Optional.ofNullable(value);
System.out.println(optionalBox.isPresent()); // 输出: false
System.out.println(optionalBox.isEmpty());  // 输出: true

 三、Optional 的常用方法

  • isPresent(): 检查 Optional 对象内部是否存在值,如果存在则返回 true,否则返回 false。

  • isEmpty(): 与 isPresent() 相反,如果 Optional 对象为空则返回 true,否则返回 false。

  • get(): 获取 Optional 对象内部的值。如果 Optional 对象为空,则抛出 NoSuchElementException。

    不推荐直接使用 get() 方法获取值,因为它没有进行空值检查,可能会导致异常。

  • orElse(other): 如果 Optional 对象包含值,则返回该值,否则返回指定的默认值 other。

  •  

    Optional<String> optionalName = Optional.empty();
    String name = optionalName.orElse("Default Name");
    System.out.println(name); // 输出: Default Name
  • orElseGet(supplier): 如果 Optional 对象包含值,则返回该值,否则调用 supplier 提供的函数生成一个默认值。 orElseGet() 方法只会在 Optional 对象为空时才执行 supplier 函数,效率更高。
  • Optional<User> optionalUser = userRepository.findUserByName("NonExistingUser");
    User user = optionalUser.orElseGet(() -> new User("Default", "User")); 
    System.out.println(user.getFullName()); // 输出: Default User
  • orElseThrow(supplier): 如果 Optional 对象包含值,则返回该值,否则抛出 supplier 提供的异常。 
  • Optional<User> optionalUser = userRepository.findUserByName("NonExistingUser");
    User user = optionalUser.orElseThrow(() -> new RuntimeException("User not found")); 
  • orElseThrow(supplier): 如果 Optional 对象包含值,则返回该值,否则抛出 supplier 提供的异常。

  • Optional<User> optionalUser = userRepository.findUserByName("NonExistingUser");
    User user = optionalUser.orElseThrow(() -> new RuntimeException("User not found")); 
  • filter(predicate): 根据指定的条件过滤 Optional 对象中的值。如果值存在且满足条件,则返回包含原始值的新的 Optional 对象;否则返回空的 Optional 对象。

  • filter(predicate): 根据指定的条件过滤 Optional 对象中的值。如果值存在且满足条件,则返回包含原始值的新的 Optional 对象;否则返回空的 Optional 对象。
  • map(function): 对 Optional 对象中的值进行转换,并返回一个包含转换后值的新的 Optional 对象。如果 Optional 对象为空,则 map 方法什么也不做,直接返回一个空的 Optional 对象。

  • Optional<User> optionalUser = userRepository.findUserByName("Albert");
    Optional<String> optionalName = optionalUser.map(User::getName);
    System.out.println(optionalName.orElse("Unknown")); // 输出: Albert
  • flatMap(function): 用于扁平化嵌套的 Optional 结构,避免引入不必要的嵌套层级。flatMap 的转换函数返回的必须是另一个 Optional 对象,如果原始的 Optional 对象为空,或者转换函数返回的 Optional 对象为空,则最终得到的也是一个空的 Optional 对象。

  •  

    Optional<User> optionalUser = userRepository.findUserByName("Albert");
    Optional<String> optionalCity = optionalUser.flatMap(u -> u.getAddress().flatMap(Address::getCity));
    System.out.println(optionalCity.orElse("Unknown City")); 
  • stream(): 将 Optional 对象转换为 Stream 对象,方便与 Stream API 进行集成。 

  • Optional<User> optionalUser = userRepository.findUserByName("Albert");
    optionalUser.stream().forEach(u -> System.out.println(u.getFullName()));

四、Optional优化案例

  • 传统方法

  • public class UserRepository {
        public User findUserByName(String name) {
            // ... (数据库查询逻辑)
            if (/* 查询结果不为空 */) {
                return new User( /* 查询结果 */ );
            } else {
                return null;
            }
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            UserRepository userRepository = new UserRepository();
            User user = userRepository.findUserByName("Albert2"); 
            if (user != null) {
                System.out.println(user.getFullName());
            } else {
                User defaultUser = new User("Neo", "Thomas Anderson");
                System.out.println(defaultUser.getFullName());
            }
        }
    }

     findUserByName() 方法返回 User 对象或 null,需要调用者进行显式 null 检

  • Optional 优化方法:

  • import java.util.Optional;
    
    public class UserRepository {
        public Optional<User> findUserByName(String name) {
            // ... (数据库查询逻辑)
            if (/* 查询结果不为空 */) {
                return Optional.of(new User( /* 查询结果 */ ));
            } else {
                return Optional.empty();
            }
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            UserRepository userRepository = new UserRepository();
            Optional<User> optionalUser = userRepository.findUserByName("Albert2");
            
            // 使用 orElse() 提供默认用户
            System.out.println(optionalUser.orElse(new User("Neo", "Thomas Anderson")).getFullName());
            
            // 使用 ifPresent() 处理存在值的情况
            optionalUser.ifPresent(user -> System.out.println(user.getFullName()));
            
            // 使用 orElseThrow() 抛出自定义异常
            User user = optionalUser.orElseThrow(() -> new RuntimeException("User not found"));
        }
    }

     

五、Optional的使用建议 

  1. 使用Optional作为方法的返回值类型,表示方法可能不返回结果。

  2. 不推荐使用Optional作为类的字段,因为会增加内存消耗,并且会使对象的序列化变得复杂。

  3. 不推荐使用Optional作为构造器参数,因为会强制调用者创建Optional实例,应该通过构造器重载来解决。

  4. 不应该用作集合的参数类型,集合本身已经可以很好地处理空集合的情况,没必要用Optional包装集合。

  5. 不建议使用get()方法,调用Optional的get()方法前没有确认值是否存在,可能会导致NoSuchElementException。

  6. 应当使用ifPresent()、orElse()、orElseGet()、orElseThrow()等方法,根据Optional对象是否包含值来执行不同的操作。

六、总结

Optional 类是 Java 提供的一个强大的工具,可以帮助我们更好地处理可能为空的值,避免 NullPointerException,提高代码质量。 

  • 34
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值