使用Java8中的Optional类来消除代码的Null检查
Optional类是Java 8新增的一个类,用以解决程序中常见的NullPointerException异常问题。本以及如何用它消除代码中的null检查。
避免使用null进行检查
对于NullPointerException异常,通常都会在异常出现的地方加上if代码块来判断值不为空,比如下面的代码:
public void bindUserToRole(User user){
if(User != null){
String roleId = user.getRoleId();
if(roleId != null){
Role role = roleDao.findOne(roleId);
if(role != null){
role.setUserId(user.getUserId());
roleDao.save(role);
}
}
}
}
使用Optional进行判断
java.util.Optional类是一个封装了Optional值的容器对象,Optional值可以为null,如果值存在,调用isPresent()方法返回true,调用get()方法可以获取值。
创建Optional对象
实例化optional对象的方法:
empty():创建一个没有值的Optional对象
Optional<String> emptyOpt = Optional.empty();
如果对emptyOpt变量调用isPresent()方法会返回false,调用get()方法抛出NullPointerException异常。
-
of()创建一个非空的Optional对象String str = "Hello"; Optional<String> notNullOpt = Optional.of(str) -
ofNullable()方法接收一个可以为null的值:Optional<String> nullableOpt = Optional.ofNullable(str);
提取Optional对象中的值
// 通常
String roleId = null;
if(user != null){
roleId = user.getRoleId();
}
// Optional
Optional<User> userOpt = Optional.ofNullable(user);
Optional<String> roleIdOpt = userOpt.map(User::getRoleId);
使用orElse()方法获取值
-
orElse():如果有值就返回,否则返回一个给定的值作为默认值
String str = "hello"; Optional<String> strOpt = Optional.of(str); String orElseResult = strOpt.orElse("hello word"); -
orElseGet():与orElse()方法作用类似,区别在于生成默认值的方式不同。该方法接受一个Supplier<? extends T>函数式接口参数,用于生成默认值
String orElseGet = strElseGet(()->"hello" ) -
orElseThrow():与前面介绍的get()方法类似,当值为null时调用这两个方法都会抛出NullPointerException异常,区别在于该方法可以指定抛出的异常类型。
String orElseThrow = strOpt.orElseThrow( ()-> new IllegalArgumentException("Argument 'str' cannot be null or blank.") ) -
ifPresent(),该方法接收一个Consumer<? super T>函数式接口,一般用于将信息打印到控制台Optional<String> strOpt = Optional.of("hellp"); strOpt.ifPresent(System.out::println) -
filer()可用于判断Optional对象是否满足给定条件,一般用于条件过滤:Optional<String> optional = Optional.of("newhzong@qq.com"); optional = optional.filter(str - >str.contains("164"));如果filter()方法中的Lambda表达式成立,filter()方法会返回当前Optional对象值
新的思维方式处理null值,Java 8提倡函数式编程,新增的许多API都可以用函数式编程表示,建议:
- 尽量避免在程序中直接调用Optional对象的get()和isPresent()方法;
- 避免使用Optional类型声明实体类的属性;
正确创建Optional对象
// 使用of与ofNullable,如果确定一个对象不能为空,应该使用of(),否则使用ofNullable()
public static void method(Role role){
// 当Optional的值通过常量获得或者通过关键字new初始化,可以直接使用of()方法
Optional<String> strOpt = Optional.of("hello");
Optional<User> userOpt = Optional.of(new User());
// 方法参数中role值不确定是否为null,使用ofNullable()方法创建
Optional<Role> roleOpt = Optional.ofNullable(role);
}
orElse()方法的使用
// 原始方法
str != null ? str: "hello";
// 使用Optional类型
return strOpt.orElse("hello")
简化if-else
User user = ...
if(User != null){
String userName = user.getUserName();
}
if( userName != null){
userName.toUpperCase();
}else{
return null;
}
User user = new User();
Optional<User> userOpt = Optional.ofNullable(user);
userOpt.map(User::getUserName)
.map(String:: toUpperCase)
.orElse(null);