2018-07-30 15:01:53 1859瀏覽
今天扣丁學(xué)堂Java培訓(xùn)老師給大家介紹一下關(guān)于Java8中Optional的一些常見錯(cuò)誤用法匯總,首先Java8引入的Optional類型,基本是把它當(dāng)作null值優(yōu)雅的處理方式。其實(shí)也不完全如此,Optional在語義上更能體現(xiàn)有還是沒有值。所以它不是設(shè)計(jì)來作為null的替代品,如果方法返回null值表達(dá)了二義性,沒有結(jié)果或是執(zhí)行中出現(xiàn)異常。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); //應(yīng)該這么用
要理解Optional的設(shè)計(jì)用意,所以語意上應(yīng)用它來表達(dá)有/無結(jié)果,不適于作為類字段與方法參數(shù)傾向于方法返回單個(gè)對(duì)象,用Optional類型表示無結(jié)果以避免null值的二義性O(shè)ptional進(jìn)行方法參數(shù)檢查不能掩蓋了錯(cuò)誤,最好是明確非法的參數(shù)輸入及時(shí)拋出輸入異常對(duì)于最后兩種不正確的用法應(yīng)熟悉Optional的源代碼實(shí)現(xiàn)就能規(guī)避。
【關(guān)注微信公眾號(hào)獲取更多學(xué)習(xí)資料】
查看更多關(guān)于“Java開發(fā)資訊”的相關(guān)文章>>