Optional
是 Java 8 中引入的一个有趣类,用于表示一个值存在或不存在。它的设计目的是解决空指针异常(NullPointerException
)问题,使得程序更加健壮、简洁。NullPointerException
异常。String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();
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();
}
}
}
}
Java8 引入的 Optional
,接下来就让我们一起看看 Optional
的魅力以及如何优化上文中又臭又长的代码。Optional
Optional
创建Optional
提供三种方式来创建 Optional
对象: // 创建包含值的 Optional 对象
Optional<String> nonEmptyOptional = Optional.of("Hello");
// 创建一个空的 Optional 对象
Optional<String> emptyOptional = Optional.empty();
// 创建包含可能为空的值的 Optional 对象
Optional<String> nullableOptional = Optional.ofNullable(null);
Optional
常用方法isPresent()
:检查值是否存在。get()
:获取值,如果值不存在会抛出 NoSuchElementException 异常。orElse(T other)
:获取值,如果值不存在则返回指定的默认值。orElseGet(Supplier<? extends T> other)
:获取值,如果值不存在则返回由 Supplier 提供的默认值。orElseThrow(Supplier<? extends X> exceptionSupplier)
:获取值,如果值不存在则抛出由 Supplier 提供的异常。 // 检查值是否存在
System.out.println("nonEmptyOptional is present: " + nonEmptyOptional.isPresent());
System.out.println("emptyOptional is present: " + emptyOptional.isPresent());
System.out.println("nullableOptional is present: " + nullableOptional.isPresent());
// 获取值
System.out.println("nonEmptyOptional value: " + nonEmptyOptional.get());
// 值为空是返回指定异常
nullableOptional.orElseThrow(() -> new IllegalStateException("field is not present"));
orElse(T other)
和 orElseGet(Supplier<? extends T> other)
Optional
为 null
public class TestMain {
public static void main(String[] args) {
Optional<String> nullableOptional = Optional.ofNullable(null);
System.out.println(nullableOptional.orElse(defaultStr()));
System.out.println(nullableOptional.orElseGet(() -> {
System.out.println("执行 defaultStr 方法 orElseGet");
return "defaultStr";
}));
}
public static String defaultStr() {
System.out.println("执行 defaultStr 方法");
return "defaultStr";
}
}
// 输出
执行 defaultStr 方法
defaultStr
执行 defaultStr 方法 orElseGet
defaultStr
Optional
不为 null
public class TestMain {
public static void main(String[] args) {
Optional<String> nullableOptional = Optional.ofNullable("123");
System.out.println(nullableOptional.orElse(defaultStr()));
System.out.println(nullableOptional.orElseGet(() -> {
System.out.println("执行 defaultStr 方法 orElseGet");
return "defaultStr";
}));
}
public static String defaultStr() {
System.out.println("执行 defaultStr 方法");
return "defaultStr";
}
}
// 输出
执行 defaultStr 方法
123
123
orElse(T other)
无论 Optional
是否 null
都会执行传入的函数获取结果值,在一些高并发的场景会造成额外的性能浪费,应尽可能选择使用 orElseGet(Supplier<? extends T> other)
。map
和 flatMap
map
和 flatMap
可以将当前值传入到参数函数中,并返回一个 Optional
对象,两者唯一的区别在于 flatMap
不会再次包装,即传入函数返回值为 Optional
类型,具体可以参考下面的例子: public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
// flatMap 不会主动包装为 Optional
return Objects.requireNonNull(mapper.apply(value));
}
}
@Builder
@Getter
class User implements Serializable {
private String name;
private Integer age;
public Optional<Integer> getAge() {
return Optional.ofNullable(age);
}
}
public class TestMain {
public static void main(String[] args) {
User user = User.builder().name("ming").age(null).build();
Optional.ofNullable(user).map(User::getName).orElse("unknown");
Optional.ofNullable(user).flatMap(User::getAge).orElse(0);
}
}
map
和 flatMap
方法十分重要,因为这是我们后文实现链式调用的关键。get
方法中一部分返回了 Optional
类型,一方面是为了演示,另一个方面可以通过这种方式可以让阅读我们代码的人明确的感知到这个字段的值可能为 null
你需要谨慎处理。filter
过滤Optional
类也提供了按条件过滤值的方法,filter()
接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional
。Optional.ofNullable(user).filter(t -> t.getName().contains("test")).orElse("unknown");
Optional
实现链式调用,首先我们需要对 User
类做一些小小的改造。@Builder
@Getter
class User implements Serializable {
private String name;
private Integer age;
private Address address;
public Optional<Integer> getAge() {
return Optional.ofNullable(age);
}
public Address getAddress() {
return address;
}
}
class Address {
private Country country;
public Optional<Country> getCountry() {
return Optional.ofNullable(country);
}
}
class Country {
private String isocode;
public Optional<String> getCountry() {
return Optional.ofNullable(isocode);
}
}
public class TestMain {
public static void main(String[] args) {
User user = User.builder().name("ming").age(null).build();
Optional.ofNullable(user).map(User::getAddress)
.flatMap(Address::getCountry)
.flatMap(Country::getIsocode)
.orElse("unknown");
}
}
Optional
重构,我们代码的可读性和健壮性都有了很大的提升。or()、ifPresentOrElse() 和 stream()
。or()
:与 orElse() 和 orElseGet() 类似,它们都在对象为空的时候提供了替代情况。or() 的返回值是由 Supplier 参数产生的另一个 Optional 对象。ifPresentOrElse()
:需要两个参数:一个 Consumer 和一个 Runnable。如果对象包含值,会执行 Consumer 的动作,否则运行 Runnable。stream()
:通过把实例转换为 Stream 对象,让我们从广大的 Stream API 中受益。如果没有值,它会得到空的 Stream;有值的情况下,Stream 则会包含单一值。Optional
是 Java 8 中引入的一个有趣类,它的设计目的是解决空指针异常(NullPointerException
)问题,我们应该好好掌握它,从而让我们在程序代码中更加优雅的处理空指针异常(NullPointerException
)问题,使我们的代码具备更好的可读性以及更加健壮。? 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
? 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。
? 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。
? 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。
? 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。
? 保持关注我的博客,让我们共同追求技术卓越。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。