前言
在日常开发中,NPE异常是导致应用程序失败的最常见原因。为了解决空指针异常,Google公司知名的 Guava项目引入了Optional类,它通过使用检查空值的方式来防止代码污染,它可以使程序员书写更干净的代码。
Optional概述
Java的Optional类其实是"进口"的,它受Guava的Optional类的启发,在JDK8中引入,Optional实际上是个容器,它可以保存泛型值,或者仅仅保存一个null,它提供了很多方便处理的方法,同时也避免了我们在书写代码的时候,进行大量显式的空值检查了。
Method
ofNullable
Optional.of()、Optional.ofNullable()都是创建Optional对象的,他们的区别of()不允许参数是null,而ofNullable()则可以。
public static void main(String[] args) {
User user1 = new User("小明");
User user2 = null;
Optional.of(user1);
Optional.ofNullable(user2);
}
orElse
主要是用来处理当值为空时候的默认值,如果有值则返回该值,否则返回设置参数值
public static void main(String[] args) {
User user1 = new User("小明");
User user2 = null;
User result = Optional.ofNullable(user2).orElse(user1);
System.out.println(result);
}
map
值映射
public static void main(String[] args) {
User user = new User("小明", null);
Integer age = Optional.ofNullable(user).map(User::getAge).orElse(-1);
}
filter
filter为过滤方法,如果filter方法中的表达式成立,方法会返回当前Optional对象值,否则返回一个值为空的 Optional对象。
public static void main(String[] args) {
User user = new User("小明", null);
Integer age = Optional.ofNullable(user)
.filter(u -> "小明".equals(u.getName()))
.map(User::getAge)
.orElse(-1);
}
isPresent
检查是否有值的另一个选择是ifPresent方法。该方法除了执行检查,还接受一个Consumer参数,如果对象不是空的,就对执行传入的表达式。
public static void main(String[] args) {
User user = new User("小明", null);
Optional.ofNullable(user)
.filter(u -> "小明".equals(u.getName()))
.ifPresent(t-> System.out.println(t.getAge()));
}
orElseGet
这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的Supplier表达式,并将返回其执行结果。
public static void main(String[] args) {
User user1 = null;
User user2 = new User("小明", null);
User result = Optional.ofNullable(user1).orElseGet( () -> user2);
}
orElse和orElseGet区别
Optional对象为空而返回orElse或orElseGet中的默认值时,并无差异,都会执行其中的代码。但Optional对象不为空时,orElse还会执行其中的代码,而orElseGet不会执行。
orElseThrow
值不存在则抛出异常,存在则什么不做。
public static void main(String[] args) {
User user1 = null;
User result = Optional.ofNullable(user1)
.orElseThrow( () -> new ServiceException());
}
Example
/**
* 防止从user中取出的数据为空,用Optional赋默认值0
*/
public static void main(String[] args) {
User user = new User("小明", null);
Integer age = null;
user.setAge(
Optional.ofNullable(age).orElse(0)
);
}
/**
* 非空则取其name,否则赋空
*/
public static void main(String[] args) {
User user1 = new User("小明", null);
User user2 = new User(null, 20);
user2.setName(
Optional.ofNullable(user1).map(User::getName).orElse("")
);
}
/**
* 多map转换
*/
public static void main(String[] args) {
Object strObj = String.valueOf("aAvwR");
Optional.ofNullable(str)
.map(Object::toString)
.map(String::toLowerCase)
.orElse("");
}
/**
* 根据姓名集合查用户集,如果结果不为空的话,取出地址构成List,否则新建List
*/
List<User> users = userDao.queryUserByNames(request.getNames());
List<String> orderNoList = Optional.ofNullable(users)
.map(u -> u.stream().map(User::getAddress)
.collect(Collectors.toList()))
.orElse(Lists.newArrayList());
/**
* 先取request实体中的AccountId,没有的话从user中取
*/
Long accountId = Optional.ofNullable(request.getAccountId())
.orElse(Optional.ofNullable(user)
.map(User::getAccountId).orElse(null));
/**
* 分页默认值
*/
paging.setOffset(
(long)Optional.ofNullable(param.getOffset()).orElse(DEFAULT_PAGE_OFFSET)
);
paging.setCount(
Optional.ofNullable(param.getCount()).orElse(DERAULT_PAGE_COUNT)
);
/**
* 替代IF输出
*/
public static void main(String[] args) {
final User user = new User("小明");
Optional.ofNullable(user.getName())
.filter(StringUtils::isNotBlank)
.ifPresent(System.out::println);
}