您的位置:

Java中的Optional类

Optional是Java 8引入的一个类,可以解决空指针异常的问题。作为一种容器对象,它可以包含T类型的值,也可以表示存在或不存在的状态。对于程序来说,这个状态很重要,因为开发人员必须时刻考虑可能出现的空值的情况,才能避免异常并提高程序的健壮性。

一、使用Optional的背景

在许多情况下,开发人员需要使用某个对象的属性或方法,但在调用之前必须检查该对象是否为null,否则将抛出NullPointerException异常。这样的检查非常乏味且容易出错,对于一些较大的代码库,人们很难甚至不可能完全避免这些问题。

为了解决这个问题,Java引入了Optional类。它在内部封装了一个确定类型的对象,并可以表示存在或不存在。这种方法不仅使代码更健壮,而且可以使代码更清晰,并使开发人员更容易理解和维护代码。

二、Optional类的使用

1、创建Optional对象

Optional.empty():创建一个空的Optional对象。

Optional<String> emptyOpt = Optional.empty();
System.out.println(emptyOpt);

运行结果:

Optional.empty

Optional.of(T value):创建一个包含给定值的Optional对象,要求传入的值必须非空。

String str = "Optional示例";
Optional<String> strOpt = Optional.of(str);
System.out.println(strOpt);

运行结果:

Optional[Optional示例]

Optional.ofNullable(T value):创建一个可空的Optional对象,如果传入值非空则包含该值,否则为空。

String strNullOrNot = null;
Optional<String> optStr = Optional.ofNullable(strNullOrNot);
System.out.println(optStr);

运行结果:

Optional.empty

2、Optional对象的使用

isPresent():如果这个Optional对象表示一个非空值,则返回true;反之返回false。

String str = "测试isPresent()方法";
Optional<String> optStrPresent = Optional.of(str);
if(optStrPresent.isPresent()) {
    System.out.println(optStrPresent.get());
}

如果Optional中有一个非空值,则运行结果为:

测试isPresent()方法

get():如果这个Optional对象包含一个值,则返回该值;否则抛出NoSuchElementException异常。

String str = "测试get()方法的异常";
Optional<String> optStrGet = Optional.empty();
try {
    System.out.println(optStrGet.get());
} catch (NoSuchElementException e) {
    System.out.println("无法调用get()方法:  " + e.getMessage());
}

运行结果:

无法调用get()方法:  No value present

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

String str = "使用orElse()方法替换空值";
Optional<String> optStrOr = Optional.empty();
String otherStr = optStrOr.orElse("字符串为空");
System.out.println(otherStr);

运行结果:

字符串为空

3、与Stream的结合使用

使用Optional值作为Stream操作的返回类型,可以帮助程序更好地处理Stream操作中出现的空值。通过使用Optional值作为返回类型,可以忽略指向可能为空的元素的引用,从而实现避免NullPointerException问题的目的。

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Optional类");
list.add(null);
list.add("使用示例");

long count = list.stream().filter(str -> str != null).count();
System.out.println("原始List集合中实际的元素个数: " + count);

Optional<String> optStr = list.stream().findFirst();
System.out.println("List集合中的第一个元素: " + optStr.get());

运行结果:

原始List集合中实际的元素个数: 3
List集合中的第一个元素: Java

三、使用Optional类的好处和注意事项

使用Optional的好处在于它可以减少为空的对象检查,使代码更加清晰并帮助程序员避免NullPointerException问题。

但是,如果不注意使用的方式,它也可能会导致更加复杂的代码,因此需要遵守一些 使用 Optional 的最佳实践。

1、不要滥用Optional

尽管Optional可以大大减少NullPointerException的出现,但也不应该滥用它。对于简单的程序,使用Optional可能会增加代码的复杂性,这可能会使程序更难理解和维护。

2、避免使用Optional作为类的属性类型

在类的设计中,最好不要将Optional作为类的属性类型。虽然这是可以做到的,但这可能会产生更加松散的类结构,从而导致更多的维护问题。

3、避免使用Optional作为返回类型

虽然Optional可以作为一种返回类型,但过度使用将会导致过于复杂的代码和性能问题。在某些情况下,选择返回列表或集合,或者仅返回 null 或其他默认值,可能更加简单和高效。

4、仅在需要时使用Optional

虽然Optional可以在许多情况下解决空值问题,但并不总是最佳工具。在绝大多数情况下,避免在模型中放置空值可能更加简单和高效。因此,应在必要时才使用Optional。

5、注意集合是否包含null值

尽管Optional可以很好地处理集合中的空值,但仍然需要注意集合中是否包含 null 值,并在需要时进行过滤和处理。否则,可能会出现NullPointerException问题。

四、总结

Optional是Java 8引入的一种新型容器,可以帮助解决空值异常问题,提高程序的健壮性。然而,如果不注意使用场景和注意事项,它可能会带来更多的复杂性。因此,开发人员应该根据自己的需求来决定是否使用Optional,以及何时使用它。