从java 8开始引入了Optional类,Optional 的出现是为了解决 NPE(NullPointerException)异常,那是怎么用呢?
在没有出现这个类之前要访问一个对象时
user.getAddress().getId()
你要先有一个很冗长的判断
if (user != null) {
if (user.getAddress() != null) {
}
}
Optional 是怎么做呢?
- 创建Optional对象
Optional<User> user1 = Optional.empty();
这样呢,也是创建了一个空的对象,在调用user1.get()
的时,也是会报错 NoSuchElementException
我们可以调用 of
和ofNullable
两个方法
of
方法是要求传入的对象不能为空
Optional<User> a = Optional.of(user);
ofNullable
传入的对象,可以为空,也可以不空
Optional<User> a = Optional.ofNullable(user);
- 访问 Optional对象
当我们利用of
和ofNullable
创建好对象之后,即可利用get()
方法取获取对象了
Optional<User> user1 = Optional.ofNullable(user);
user1.get();
再看他的源码,仍然有可能会报错
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
那我们可以先调用 ifPresent()
方法 ,可以先验证当前值是否为null
Optional<User> user1 = Optional.ofNullable(user);
if(user1.isPresent()) {
user1.get();
}
同样还有另一个方法也可以处理,ifPresent()
,该方法通过传入一个Consumer
,如果不为空,就会执行传入的Lambda 表达式
Optional<User> user1 = Optional.ofNullable(user);
user1.ifPresent( x-> {
System.out.println(x.getId());
});
3.返回默认值
Optional 的 API 提供了返回对象值,或是在为空的情况下返回默认值
orElse
和orElseGet
方法分别提供了两个选择
- orElse
@Test
public void testOrElse() {
User a = null;
User b = new User("b", "bname");
User result = Optional.ofNullable(a).orElse(b);
Assert.assertEquals("b", result.getId());
}
上面的结果会返回 b对象
- orElseGet
@Test
public void testOrElseGet() {
User a = null;
User b = new User("b", "bname");
User result = Optional.ofNullable(a).orElseGet(() -> b);
Assert.assertEquals("b", result.getId());
}
同样是返回b的对象
这是在a都为空的情况下,执行的结果是一样的
那如果a不为空的情况下呢?
我们先来重构下,把创建 b对象的提取出来,同时增加日志
public User createUser() {
System.out.println("logging create user b");
return new User("b", "bname");
}
来测试下orElse
@Test
public void testOrElse() {
User a = new User("a", "aname");
User result = Optional.ofNullable(a).orElse(createUser());
Assert.assertEquals("a", result.getId());
}
看输出结果,也是会执行createUser()
再来看下 orElseGet
@Test
public void testOrElseGet() {
User a = new User("a", "aname");
User result = Optional.ofNullable(a).orElseGet(() -> createUser());
Assert.assertEquals("a", result.getId());
}
输出结果,并不会输出create user b 的日志
其实也很好理解的,因为orElse 方法是一定要先创建好对象作为参数的,而orElseGet 是通过lambda 函数传入,只有为空的情况下,才会调用这个方法,所以在调用这些方法的时候,
要很注意
,由其是有操作网络连接相关的操作时,要按实际情况来决定使用哪个方法作为默认值的提供方
网友评论