Java8 提供的Optional<T>让java程序员不用再老检查null,就是在任何对象前面包一层Optional,然后直接用这个Optional对象就行了。判空在optional内部进行。
常见写法:
User findUserById(String userId) { ... };
User user = findUserById("667290");
if(user!=null){
System.out.println("User's Name = " + user.getName());
}
不是所有的时候都会记得写if(user!=null),引入Optional之后的写法:
Optional<User> findUserById(String userId) { ... };
Optional<User> optionalUser = findUserById("667290");
optionalUser.ifPresent(user -> {
System.out.println("User's name = " + user.getName());
})
ifPresent()这个函数在optionalUser不为空的时候会被调用,否则什么都不做。
创造Optional 对象
1 创造空对象
Optional<User> user = Optional.empty(); //而不是 User user = null;
2.创造非空对象
User user = new User("667290", "Rajeev Kumar Singh");
Optional<User> userOptional = Optional.of(user);
3.用一个可能为空的对象创造一个Optional对象
Optional<User> userOptional = Optional.ofNullable(user); // 如果user为空,返回 Optional.empty(),否则返回一个 Optional<User> 对象
判断为空 optional.isPresent()
if(optionalUser.isPresent()) {
// value is present inside Optional
System.out.println("Value found - " + optionalUser.get());
} else {
// value is absent
System.out.println("optionalUser is empty");
}
- 判断为空 ifPresent()
optionalUser.ifPresent(value -> {
System.out.println("Value found - " + value);
});
ifPresent 可以传入一个lambda表达式,如果为空则不执行。
从Optional对象里获取对象
optionalUser不为空,则get获取到user,否则报错 [NoSuchElementException],所以在这里还是需要先isPresent或者ifPresent判断为空。
User user = optionalUser.get();
返回不为空的默认值orElse()
optional为空,则直接返回一个默认对象
比如,我们不想ruturn一个null,而是想return一个id为0的用户:
optionalUser=...
User finalUser = optionalUser.orElse(new User("0", "Unknown User"));
//老的写法
//user = ...
//User finalUser = (user != null) ? user : new User("0", "Unknown User");
返回不为空的默认值orElseGet()
optional为空,则直接返回一个函数执行结果。
User finalUser = optionalUser.orElseGet(() -> {
return new User("0", "Unknown User");
});
抛出异常 orElseThrow()
Optional 为空,抛出异常。
@GetMapping("/users/{userId}")
public User getUser(@PathVariable("userId") String userId) {
return userRepository.findByUserId(userId).orElseThrow(
() -> new ResourceNotFoundException("User not found with userId " + userId);
);
}
增加if逻辑 filter()
比如说,只对男性进行处理。
userOptional不为空,并且满足“MALE”,会执行ifPresent里的函数,否则返回一个empty Optional
userOptional.filter(user -> user.getGender().equalsIgnoreCase("MALE"))
.ifPresent(() -> {
// 只在userOptional不为空并且为男性的时候执行
})
//老的写法:
//if(user != null && user.getGender().equalsIgnoreCase("MALE")) {
// // Todo
//}
数据处理 map()
比如获取用户的地址为“india”的用户的地址。map()会返回用户地址,如果用户为空或者地址为空,则返回 optional empty
userOptional.flatmap(User::getAddress)
.filter(address -> address.getCountry().equalsIgnoreCase("india"))
.ifPresent(() -> {
System.out.println("User belongs to India"); // 用户不为空,用户地址也不为空才执行
});
// 老的写法:
//if(user != null) {
// Address address = user.getAddress();
// if(address != null && address.getCountry().equalsIgnoreCase("India")) {
// System.out.println("User belongs to India");
// }
//}
常见的数据转换:
public String getCity(User user) throws Exception{
if(user!=null){
if(user.getAddress()!=null){
Address address = user.getAddress();
if(address.getCity()!=null){
return address.getCity();
}
}
}
throw new Excpetion("取值错误");
}
//新写法:
public String getCity(User user) throws Exception{
return Optional.ofNullable(user)
.map(u-> u.getAddress())
.map(a->a.getCity())
.orElseThrow(()->new Exception("取指错误"));
}