2018-07-30 15:01:53 552浏览
今天扣丁学堂Java培训老师给大家介绍一下关于Java8中Optional的一些常见错误用法汇总,首先Java8引入的Optional类型,基本是把它当作null值优雅的处理方式。其实也不完全如此,Optional在语义上更能体现有还是没有值。所以它不是设计来作为null的替代品,如果方法返回null值表达了二义性,没有结果或是执行中出现异常。Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”, and using null for such was overwhelmingly likely to cause errors.
Reports any uses of java.util.Optional<T> , java.util.OptionalDouble , java.util.OptionalInt , java.util.OptionalLong or com.google.common.base.Optional as the type for a field or parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result". Using a field with type java.util.Optional is also problematic if the class needs to be Serializable , which java.util.Optional is not.
public class User { private String firstName; private Optional<String> middleName = Optional.empty(); private String lastName; public void setMiddleName(Optional<String> middleName) { this.middleName = middleName; } public String getFullName() { String fullName = firstName; if(middleName != null) { if(middleName.isPresent()){ fullName = fullName.concat("." + middleName.get()); } return fullName.concat("." + lastName); } }
user.setMiddleName(Optional.empty()); user.setMiddleName(Optional.of("abc"));
private String middleName; public void updateMiddleName(Optional<String> middleName) { if(middleName != null) { this.middleName = middleName.orElse(null); } else { this.middleName = null; } }
public User getUserById(String userId) { if(userId != null) { return userDao.findById(userId); } else { return null; } }
return if(Optional.ofNullable(userId) .map(id -> userDao.findById(id)) .orElse(null);
userDao.findById(...) getUserById(userId)
public User getUserById(String userId) { //抛出出 NullPointerException 如果 null userId return userDao.findById(Objects.requireNoNull(userId, "Invalid null userId"); } //or public User getUserById(String userId) { //抛出 IllegalArgumentException 如果 null userId Preconditions.checkArgument(userId != null, "Invalid null userId"); return userDao.findById(userId); }
public User getUserById(String userId) { return Optional.ofNullable(userId) .map(id -> userDao.findById(id)) orElseThrow(() -> new RuntimeException("userId 是 null 或 findById(id) 返回了 null 值")); }
String productId = Optional.ofNullable(user) .map(User::getOrder) .flatMap(order -> Optional.ofNullable(order.getProduct())) //1 .flatMap(product -> Optional.ofNullable(product.getId())) //2 .orElse("");
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } }
String productId = Optional.ofNullable(user) .map(User::getOrder) .map(order -> order.getProduct()) //1 .map(product -> product.getId()) //2 .orElse("");
public Optional<User> getUserById(String userId) { if("ADMIN".equals(userId)) { User adminUser = new User("admin"); return Optional.ofNullable(adminUser); //1 } else { return userDao.findById(userId); } }
public static <T> Optional<T> of(T value) { return new Optional<>(value); } public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
Optional.ofNullable(100); //这样不好 Optional.of(100); //应该这么用
要理解Optional的设计用意,所以语意上应用它来表达有/无结果,不适于作为类字段与方法参数倾向于方法返回单个对象,用Optional类型表示无结果以避免null值的二义性Optional进行方法参数检查不能掩盖了错误,最好是明确非法的参数输入及时抛出输入异常对于最后两种不正确的用法应熟悉Optional的源代码实现就能规避。
【关注微信公众号获取更多学习资料】