共计 5963 个字符,预计需要花费 15 分钟才能阅读完成。
本文已收录至 GitHub,举荐浏览 👉 Java 随想录
微信公众号:Java 随想录
原创不易,重视版权。转载请注明原作者和原文链接
在编程世界中,「空指针异样(NullPointerException)」无疑是咱们最常遇到的 ” 罪魁祸首 ” 之一。它像一片荫蔽的地雷,静静地期待着咱们不小心地踏入,给咱们的代码带来潜在的威逼。这种问题尽管看似渺小,但却无奈漠视。甚至可能对整个程序的稳定性产生重大影响。
为了应答这个长久以来困扰开发者的问题,Java 8 版本引入了一个弱小的工具——Optional 类。
Optional 不仅仅是一个容器,它更是一种编程理念的转变,让咱们能够用更优雅的形式解决可能为空的状况。
在本篇博客中,我将向大家介绍 JDK Optional 类及其应用办法,帮忙你从根本上杜绝空指针异样,晋升代码品质。
Optional 介绍
Optional 类是一个容器对象,它能够蕴含或不蕴含非空值。如果一个对象可能为空,那么咱们就能够应用 Optional 类来代替该对象。
Optional 类型的变量能够有两种状态:存在值和不存在值。
Optional 类有两个重要的办法:of 和 ofNullable:
- of 办法用于创立一个非空的 Optional 对象,如果传入的参数为 null,则会抛出 NullPointerException 异样。
- ofNullable 办法用于创立一个能够为空的 Optional 对象。如果传入的参数为空,则返回一个空的 Optional 对象。当 Optional 对象存在值时,调用 get() 办法能够返回该值,当 Optional 对象不存在值时,调用 get() 办法会抛出 NoSuchElementException 异样。
上面是一个应用 Optional 类的例子:
Optional<String> optional = Optional.of("Hello World");
System.out.println(optional.get()); // 输入 Hello World
在下面的例子中,咱们首先应用 of() 办法创立了一个蕴含字符串 “Hello World” 的 Optional 对象,而后应用 get() 办法获取该对象的值并将其打印进去。
留神,如果咱们尝试创立一个 null 值的 Optional 对象,则会抛出 NullPointerException 异样。
在应用 Optional 类时,咱们应该尽量避免应用 isPresent()
和 get()
办法,因为这些办法可能会引起空指针异样。比拟举荐应用 Optional.ofNullable() 来创立一个 Optional 对象。
Optional 应用
创立 Optional 对象
咱们能够应用以下几种形式来创立 Optional 对象:
Optional.of(value)
:创立一个蕴含非空值的 Optional 对象。Optional.empty()
:创立一个不蕴含任何值的空 Optional 对象。Optional.ofNullable(value)
:创立一个 可能蕴含 null 值的 Optional 对象。如果 value 不为 null,则该办法会创立一个蕴含该值的 Optional 对象;否则,创立一个空 Optional 对象。
上面是一个应用 Optional.ofNullable()
办法的例子:
String str = null;
Optional<String> optional = Optional.ofNullable(str);
System.out.println(optional.isPresent()); // 输入 false
在下面的例子中,咱们首先申明了一个空字符串 str,并将其赋值为 null。而后,咱们应用 ofNullable()
办法创立了一个 Optional 对象。因为 str 是 null,因而创立的 Optional 对象也是空的。最初,咱们应用 isPresent()
办法查看 Optional 对象是否蕴含值。
orElse()与 orElseGet()
orElse()
办法接管一个参数,即为默认值。如果 Optional 对象中的值不为空,则返回该值,否则返回传入的默认值。具体用法如下:
Optional<String> optional = Optional.ofNullable(null);
String result = optional.orElse("default");
System.out.println(result); // 输入 "default"
orElseGet()
办法与 orElse()
办法相似,也是用于获取默认值的办法。然而,orElseGet()
办法接管的参数是一个「Supplier 函数式接口」,用于在须要返回默认值时生成该值。具体用法如下:
Optional<String> optional = Optional.ofNullable(null);
String result = optional.orElseGet(() -> "default");
System.out.println(result); // 输入 "default"
orElse() 和 orElseGet()的区别
orElse()
和 orElseGet()
特地类似,有必要抽离进去讲下他们之间的区别。
orElse()
办法无论 Optional 对象是否为空都会执行,因而它总是会创立一个新的对象。orElseGet()
办法只有在 Optional 对象为空时才会执行,因而它能够用来提早创立新的对象。
用一个例子感受一下:
@Test
void test() {System.out.println("-------- 不为 null 的状况 ----------");
// 不为 null
String str1 = "hello";
String result11 = Optional.ofNullable(str1).orElse(get(str1 + ":orElse()办法被执行了"));
String result12 = Optional.ofNullable(str1).orElseGet(() -> get(str1 + ":orElseGet()办法被执行了"));
System.out.println(result11);
System.out.println(result12);
System.out.println("-------- 为 null 的状况 ----------");
// 为 null
String str2 = null;
String result21 = Optional.ofNullable(str2).orElse(get(str1 + ":orElse()办法被执行了"));
String result22 = Optional.ofNullable(str2).orElseGet(() -> get(str2 + ":orElseGet()办法被执行了"));
System.out.println(result21);
System.out.println(result22);
}
public String get(String name) {System.out.println(name);
return name;
}
输入后果如下:
-------- 不为 null 的状况 ----------
hello:orElse()办法被执行了
hello
hello
-------- 为 null 的状况 ----------
hello:orElse()办法被执行了
null:orElseGet()办法被执行了
hello:orElse()办法被执行了
null:orElseGet()办法被执行了
因而,一般来说,如果你心愿在 Optional 对象为空时才创立新的对象,能够应用 orElseGet()
办法。否则,如果你心愿总是创立新的对象,无论 Optional 对象是否为空,能够应用 orElse()
办法,通常来说 orElseGet()
更佳,集体也是举荐应用orElseGet()
。
map()与 flatMap()
map()
办法承受一个函数作为参数,该函数将被利用于 Optional 对象中的值。如果 Optional 对象存在值,则将该值传递给函数进行转换,否则返回一个空 Optional 对象。
上面是一个应用 map() 办法的例子:
String str = "Hello";
Optional<String> optional = Optional.of(str);
Optional<String> upperCaseOptional = optional.map(String::toUpperCase);
System.out.println(upperCaseOptional.get()); // 输入 HELLO
在下面的例子中,咱们首先应用 of()
办法创立了一个蕴含字符串 “Hello” 的 Optional 对象。而后,咱们应用 map()
办法将该字符串转换为大写模式,并将后果存储到另一个 Optional 对象 upperCaseOptional 中。最初,咱们应用 get()
办法获取 upperCaseOptional 对象中的值并打印进去。
flatMap()
办法与 map()
办法相似,都承受一个函数作为参数。然而,flatMap()
办法返回的是一个 Optional 类型的值。如果函数返回的是一个 Optional 对象,则该办法会将其 ” 开展 ”,否则返回一个空 Optional 对象。
上面是一个应用 flatMap() 办法的例子:
String str = "hello world";
Optional<String> optional = Optional.of(str);
Optional<Character> result = optional.flatMap(s -> {if (s.length() > 0)
return Optional.of(s.charAt(0));
else
return Optional.empty();});
System.out.println(result.get()); // 输入 h
在下面的例子中,咱们首先创立了一个蕴含字符串 “hello world” 的 Optional 对象。而后,咱们应用 flatMap()
办法将该字符串转换为第一个字符,并将后果存储到另一个 Optional 对象 result 中。最初,咱们应用 get()
办法获取 result 对象中的值并打印进去。
filter()
filter() 办法承受一个「谓词(Predicate)」作为参数,返回一个 Optional 类型的值。如果 Optional 对象存在值且满足谓词的条件,则返回该 Optional 对象,否则返回一个空 Optional 对象。
上面是一个应用 filter() 办法的例子:
Integer number = 10;
Optional<Integer> optional = Optional.of(number);
Optional<Integer> result = optional.filter(n -> n % 2 == 0);
System.out.println(result.isPresent()); // 输入 true
在下面的例子中,咱们首先创立了一个蕴含整数 10 的 Optional 对象。而后,咱们应用 filter()
办法过滤出该数字是否为偶数,并将后果存储到另一个 Optional 对象 result 中。最初,咱们应用 isPresent()
办法查看 result 对象是否存在值。
罕用办法
咱们曾经介绍了 Optional 类的几种罕用办法。除此之外,咱们这里再逐个列举和解析其余办法。
办法名 | 阐明 |
---|---|
empty() |
返回一个空的 Optional 实例。 |
of(T value) |
返回一个蕴含给定非 null 值的Optional 。如果 value 为 null,会抛出 NullPointerException。 |
ofNullable(T value) |
返回一个可选的蕴含给定值的Optional ,也可能为空。 |
get() |
如果 Optional 有值则将其返回,否则抛出NoSuchElementException 。 |
isPresent() |
如果值存在返回 true,否则 false。 |
isEmpty() |
如果值不存在返回 true,否则 false。(Java 11 后新增) |
ifPresent(Consumer<? super T> consumer) |
如果值存在,则应用该值调用指定的消费者,否则不执行任何操作。 |
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) |
如果值存在,则应用该值调用指定的消费者,否则执行指定的无参数的动作。(Java 9 后新增) |
filter(Predicate<? super T> predicate) |
如果一个值存在,并且这个值给定的 predicate 对其返回 true,返回一个 Optional 形容的值,否则返回一个空的Optional 。 |
map(Function<? super T,? extends U> mapper) |
如果有值,利用 mapping 函数并返回后果。否则返回空的Optional 。 |
flatMap(Function<? super T,Optional<U>> mapper) |
如果值存在,返回从 Optional 中提取的值,否则返回一个空的Optional 。 |
orElse(T other) |
如果存在该值,返回值,否则返回other 。 |
orElseGet(Supplier<? extends T> other) |
如果存在该值,返回值,否则触发 other 并返回。 |
orElseThrow() |
如果存在该值,返回蕴含的值,否则抛出NoSuchElementException 。 |
orElseThrow(Supplier<? extends X> exceptionSupplier) |
如果存在该值,返回蕴含的值,否则抛出由 Supplier 产生的异样。 |
在这篇文章中,咱们深入探讨了 Java 的 Optional 类及其在编程实际中的利用。通过应用 Optional,咱们能够更无效地解决可能存在的空值状况,从而防止运行时的 NullPointException。尽管它引入了额定的复杂性,但如果正确应用,它能够提供更清晰、更易于保护的代码。
然而,重要的是要记住,Optional 并不是解决所有问题的银弹。像所有工具一样,咱们须要理解它的长处和局限性,并确保在适当的场景下应用它。编程始终是一个学习和摸索的过程,Optional 只是咱们工具箱中的一个工具。心愿通过本文,你对如何利用 Java 的 Optional 类有了更全面的了解。
感激浏览,如果本篇文章有任何谬误和倡议,欢送给我留言斧正。
老铁们,关注我的微信公众号「Java 随想录」,专一分享 Java 技术干货,文章继续更新,能够关注公众号第一工夫浏览。
一起交流学习,期待与你共同进步!