参考资料:
Java8 Optional用法和最佳实践 - 掘金
一、背景
根据Oracle文档,Optional是一个容器对象,可以包含也可以不包含非null值。Optional在Java 8中引入,目的是解决 NullPointerExceptions的问题。本质上,Optional是一个包装器类,其中包含对其他对象的引用。在这种情况下,对象只是指向内存位置的指针,并且也可以指向任何内容。从其它角度看,Optional提供一种类型级解决方案来表示可选值而不是空引用。
在Optional之前
在Java 8之前,程序员将返回null而不是Optional。这种方法有一些缺点。一种是没有明确的方法来表示null可能是一个特殊值。相比之下,在API中返回Optional是明确的声明,其中可能没有值。如果我们要确保不会出现空指针异常,则需要对每个引用进行显式的空检查,如下所示,我们都同意这是很多样板。
// Life before Optionalprivate void getIsoCode( User user){if (user != null) {Address address = user.getAddress();if (address != null) {Country country = address.getCountry();if (country != null) {String isocode = country.getIsocode();if (isocode != null) {isocode = isocode.toUpperCase();}}}}}
为了避免上述繁杂 的 !=null ,我们可以引入Optional
二、Optional类的对象创建
均为静态方法创建
1. Optional.empty()
//第一种创建方式Optional<String> optional=Optional.empty();//判断是否为空. 此时为 空null,System.out.println(optional.isEmpty());//判断是否存在。此时不存在,返回falseSystem.out.println(optional.isPresent());//如果optional为null,则会出现异常. System.out.println(optional.get());
2.Optional.of()
//第二种创建方式//Optional<String> optional=Optional.of(null); //value 不能为null,不然会报错Optional<String> optional1=Optional.of("123");System.out.println(optional1.get());
3. Optional.ofNullable()
三、检查Optional的value是否存在
下面代码中包含了3种判断方法
Optional<String> optional=Optional.ofNullable(null);//1.boolean empty = optional.isEmpty();//2.boolean present = optional.isPresent();//3.optional.ifPresent(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println("一旦存在,就调用我这个方法");}});
这个filter方法,有点意思,可以自己去判断是否满足一个条件,满足则创建一个新的Optional对象并且value跟所要判断的optional的value一致。否则返回一个Optional.empty()
四、获取value的方法
让gpt解释一下 orElse() 与orElseGet()的区别
五、Optional的最佳实践
当你在编写项目时使用 Optional 类型时,以下是一些最佳实践建议:
-
不要将 Optional 用于方法参数或字段类型
- Optional 类型主要用于表示可能存在空值的返回值类型。
- 如果将其用于方法参数或字段类型,则可能会使代码变得复杂,甚至不必要。
-
尽量避免使用 Optional 的 get() 方法
- Optional 的 get() 方法可以用于获取 Optional 对象中的值,但如果 Optional 对象为空,则会抛出 NoSuchElementException 异常。
- 因此,为了避免异常的发生,最好使用其他方法来处理 Optional 对象的值,比如 orElse() 或 orElseGet()。
-
使用 Optional 来处理返回值为空的情况
- 如果一个方法可能返回 null,应该考虑使用 Optional 类型来代替。
- 这样可以更明确地表示空值的含义,并提供更加优雅的语法来处理空值的情况。
-
使用 Optional 与 Stream API 结合使用
- Optional 和 Stream API 是 Java 8 中引入的两个重要特性。
- 它们结合使用可以提高代码的可读性和简洁性。
- 可以使用 Optional 的 filter() 和 map() 方法来对 Stream 进行过滤和转换操作,从而生成新的 Optional 对象。
// 示例 1:使用 Optional 来处理返回值为空的情况
public Optional<String> getOptionalValue(String key) {String value = getValueByKey(key);return Optional.ofNullable(value);
}// 示例 2:使用 Optional 和 Stream API 进行过滤操作
public Optional<User> findUserByName(String name) {List<User> userList = getUserList();return userList.stream().filter(user -> user.getName().equals(name)).findFirst();
}// 示例 3:使用 orElse() 方法提供默认值
Optional<String> optional = Optional.empty();
String result = optional.orElse("default value");// 示例 4:使用 orElseGet() 方法提供默认值
Optional<String> optional = Optional.empty();
String result = optional.orElseGet(() -> generateDefaultValue());// 示例 5:使用 map() 方法将 Optional 对象中的值转换为其他类型
Optional<String> optional = Optional.of("hello");
Optional<Integer> lengthOptional = optional.map(String::length);// 示例 6:使用 flatMap() 方法展开 Optional 对象
Optional<Optional<String>> optional = Optional.of(Optional.of("hello"));
Optional<String> flattenedOptional = optional.flatMap(Function.identity());
关于示例6的一些解释: