Java8 引入的 Optional类。主要用来解决空指针异常(NullPointerException)
,空指针异常是导致Java应用程序失败的最常见原因。
Optional类可以理解为一个容器:它既可以保存类型T的对象,也可以保存null。
Optional类提供了很多有用的方法,并实现了检查空值的功能,程序员就不用显式地写空值检测的代码,再结合函数式编程,使得代码更加干净,简洁。
一、Optional类的使用
1、创建 Optional实例
Optional类可以理解为一个容器:它既可以保存类型 T的对象,也可以保存 null。
1.1 of方法
of:为非null的值创建一个optional,如果传入为null,则会空指针。
@Test
public void testOf(){
JUser jUser = new JUser();
jUser.setId(100L);
jUser.setUsername("赵云");
jUser.setPazzword("abc123");
jUser.setHeight(1.78D);
jUser.setBirthday(new Date());
jUser.setStatus(JUserStatusEnum.ACTIVATE);
Optional<JUser> optionalJUser = Optional.of(jUser);
System.out.println(optionalJUser.get()); // 输出结果:jUser信息
jUser = null;
Optional<JUser> optionalJUser2 = Optional.of(jUser);
System.out.println(optionalJUser2.get()); // 输出结果:java.lang.NullPointerException
}
1.2 ofNullable方法
ofNullable:为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
@Test
public void testOfNullable(){
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
System.out.println(optionalJUser); // 输出结果:Optional.empty
JUser jUser1 = optionalJUser.get();// 输出结果:在这一行报错啦,java.lang.NullPointerException: No value present
}
1.3 empty方法
empty:返回一个空 Optional实例。
注意: Optional.empty() 所有保存 null包装成的 Optional对象,而且是单例模式
的。与泛型无关。
@Test
public void testEmpty(){
Optional<Object> empty = Optional.empty();
System.out.println(empty); // 输出结果:Optional.empty
Object o1 = Optional.<Integer>empty();
Object o2 = Optional.<String>empty();
System.out.println(o1 == o2);// 输出结果:true
}
2、验证 Optional实例
2.1 isPrensent方法
isPrensent:如果值存在返回true,不存在返回false。
@Test
public void testIsPresent(){
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
boolean present = optionalJUser.isPresent();
System.out.println(present); // 输出结果:false
}
2.2 ifPresent方法
ifPresent:接受一个Consumer参数,如果对象不为空,就调用consumer接口。否则不做处理。
@Test
public void testIfPresent(){
JUser jUser = new JUser();
jUser.setId(100L);
jUser.setUsername("赵云");
jUser.setPazzword("abc123");
jUser.setHeight(1.78D);
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
optionalJUser.ifPresent(u -> {
// 不为 null时才会执行断言
System.out.println(u);// 输出结果:jUser信息
});
}
3、Optional实例使用
3.1 get方法
get:如果有值则返回,没有值抛出
NoSuchElementException异常
@Test
public void testGet(){
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
// JUser jUser1 = optionalJUser.get(); // 输出结果:java.lang.NullPointerException
// 可以使用 isPresent方法检查
if(optionalJUser.isPresent()){
System.out.println(optionalJUser.get());// 输出结果:此时为空,不执行该语句
}
}
3.2 orElse(方法
orElse(T other):如果保存的值不是null,则返回原来的值,否则返回 other。
@Test
public void testOrElse(){
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
JUser jUser1 = optionalJUser.orElse(new JUser());
System.out.println(jUser1);// 输出结果:jUser实例的默认信息
// JUser{id=null, username='null', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null}
}
3.3 orElseGet方法
orElseGet(Supplier<? extends T> other):
如果保存的值不是null,则返回原来的值,否则调用 生产者函数 并返回调用结果的。
@Test
public void testOrElseGet(){
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
JUser jUser1 = optionalJUser.orElseGet(() -> {
JUser u = new JUser();
u.setId(100L);
u.setUsername("赵云");
return u;
});
System.out.println(jUser1);// 输出结果:u实例信息
// JUser{id=100, username='赵云', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null}
}
注意:orElse和 orElseGet方法的区别
- 如果 Optional保存的是 null值时,两者调用方法的效果一样的。但是,orElse可以返回任何类型 T的值,而 orElseGet必须是 Supplier函数返回的调用结果。
- 如果 Optional保存的不是 null值时,两者调用方法的效果一样的。
3.4 orElseThrow方法
orElseThrow(Supplier<? extends X> exceptionSupplier):有值返回,没有值抛出 supplier接口创建的异常
@Test
public void testOrElseThrow(){
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
JUser jUser1 = optionalJUser.orElseThrow(() -> {
return new RuntimeException("testOrElseThrow ");
});
// 输出结果:java.lang.RuntimeException: testOrElseThrow
}
3.5 map方法
map(Function<? super T,? extends U> mapper):
有值,就调用 Function函数并返回生成的值。否则返回空的Optional。
@Test
public void testMap(){
JUser jUser = new JUser();
jUser.setId(100L);
jUser.setUsername("赵云");
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
Optional<JUser> optionalJUser1 = optionalJUser.map((u) -> {
u.setId(u.getId() + 100L);
u.setUsername("赵云2");
return u;
});
System.out.println(optionalJUser1.get());// 输出结果:JUser{id=200, username='赵云2', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null}
// 如果 jUser= null,则输出结果:java.lang.NullPointerException
}
3.6 flatMap方法
flatMap(Function<? super T, ? extends Optional<? extends U>> mapper):
它map类似,区别在于他调用结束的时候,不会对Optional做一个封装
@Test
public void testFlatMap() {
JUser jUser = new JUser();
jUser.setId(100L);
jUser.setUsername("赵云");
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
Optional<JUser> optionalJUser1 = optionalJUser.flatMap((u) -> {
//需要我们自己的去封装一个Optional
u.setId(u.getId() + 100L);
u.setUsername("赵云2");
return Optional.of(u);
});
System.out.println(optionalJUser1.get());// 输出结果:JUser{id=200, username='赵云2', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null}
// 如果 jUser= null,则输出结果:java.lang.NullPointerException
}
3.7 filter方法
filter:有值,返回满足条件的Optional。否则返回空的Optional
@Test
public void testFilter() {
JUser jUser = new JUser();
jUser.setId(100L);
jUser.setUsername("赵云");
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
// 没有满足的,返回空的Optional
Optional<JUser> optionalJUser1 = optionalJUser.filter(u -> {
return u.getId() == 1;
});
System.out.println(optionalJUser1.get());// 输出结果:java.util.NoSuchElementException: No value present
}
4、Optional类的链式方法
二、JDK9的增强
上面介绍了 Java 8 的特性,Java 9 为 Optional 类添加了三个方法:
- or()
- ifPresentOrElse()
- stream()。
1、or方法
or() 方法与 orElse() 和 orElseGet() 类似,它们都在对象为空的时候提供了替代情况。
or() 的返回值是由 Supplier 参数产生的另一个 Optional 对象。
@Test
public void testOr() {
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
Optional<JUser> optionalJUser1 = optionalJUser.or(() -> {
JUser u = new JUser();
u.setId(100L);
u.setUsername("赵云");
return Optional.of(u);
});
System.out.println(optionalJUser1.get());// 输出结果:u信息
}
2、ifPresentOrElse方法
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction):
如果对象包含值,会执行 Consumer 的动作,否则运行 Runnable。
@Test
public void testIfPresentOrElse() {
JUser jUser = null;
Optional<JUser> optionalJUser = Optional.ofNullable(jUser);
optionalJUser.ifPresentOrElse(u -> System.out.printf("user id = {}" + u.getId()),
() -> System.out.printf("User not found"));
// 输出结果:User not found
}
3、stream方法
stream() 方法,它通过把实例转换为 Stream对象,让你从广大的 Stream API中受益。如果没有值,它会得到空的 Stream;有值的情况下,Stream则会包含单一值。
@Test
public void testStream() {
JUser jUser = new JUser();
jUser.setId(100L);
jUser.setUsername("赵云");
List<JUser> jUserList = Optional.ofNullable(jUser)
.stream()
.filter(u -> u.getId() == 100)
.map(u -> {
u.setId(u.getId() + 100L);
u.setUsername("赵云2");
return u;
})
.collect(Collectors.toList());
System.out.println(jUserList);// 输出结果:数据
}
总结:
Optional 是 Java 语言的有益补充 —— 它旨在减少代码中的 NullPointerExceptions,虽然还不能完全消除这些异常。它也是精心设计,自然融入 Java 8 函数式支持的功能。
总的来说,这个简单而强大的类有助于创建简单、可读性更强、比对应程序错误更少的程序。
参考文章:
- 理解、学习与使用 Java 中的 Optional:https://www.cnblogs.com/zhangboyu/p/7580262.html
– 求知若饥,虚心若愚。