開發相關知識點整理,內容來自個人我的網站筆記,和收集參考的資料,因爲是發在社區,整理了排版和可讀性,對於內容我儘可能作到是通過驗證的,以避免誤人子弟。固然本人能力有限,若有錯誤或疑問,歡迎一塊兒討論和指正(有些內容也是我參考別人的,若有侵權,請聯繫我,通常我會註明轉載和參考原文)前端
一句話歸納: 它是一個容器,用來包裝對象,解決NullPointerException異常的java
static Optional empty() :用來建立一個空的Optionalweb
static Optional of(T value) :用來建立一個非空的Optional後端
static Optional ofNullable(T value) :用來建立一個多是空,也可能非空的Optionalapp
其實上面這三個方法,看一下源碼就很清晰了,好比of函數
// 方法
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
// 構造器
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
// Objects對象的requireNonNull方法
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
複製代碼
of方法建立Optional對象,並對傳入值作NullPointerException異常判斷,因此,當你傳遞一個null值的時候,就會觸發異常了工具
再看看empty方法網站
// 方法
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
// 靜態常量
private static final Optional<?> EMPTY = new Optional<>();
// 常量
private final T value;
// 構造器
private Optional() {
this.value = null;
}
複製代碼
一開始就定義了一個Optional<?> EMPTY
的對象,而且構造函數使用默認的,value爲空。empty只是作了泛型的轉換ui
剩下的ofNullable就更簡單了,經過傳遞的值決定使用of仍是emptythis
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
複製代碼
Optional類的源碼仍是比較簡單的,代碼不多,經過成員變量和構造方法的解讀,相信你已經理解了of,empty,ofNullable
最正確的作法就是對須要作NullPointerException異常判斷的對象,把它包裝成Optional類,而後指明對象不存在的時候,應該怎麼作,下面來看一下幾種常見的用法
public class OptionalTest {
public static void main(String[] args) {
HashMap<Integer, User> userHashMap = new HashMap<>();
userHashMap.put(1, new User(1, "Xiao Ming"));
userHashMap.put(2, new User(2, "Xiao Zhi"));
userHashMap.put(3, null);
UserUtil userUtil = new UserUtil(userHashMap); // 這個工具類只是爲了填充數據的,不要在乎這些細節,getUserByUserId方法能返回User對象
// 包裝了User對象,而且使用orElse指明瞭對象不存在的時候應該返回指定的值,也就是new User(1, "Xiao Bai")
User user = Optional
.ofNullable(UserUtil.getUserByUserId(2))
.orElse(new User(1, "Xiao Bai"));
}
}
// 工具類,隨便寫的,經過hashMap模擬查詢用戶
public class User {
public Integer id;
public String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
}
class UserUtil {
public static HashMap<Integer, User> hashMap;
UserUtil(HashMap<Integer, User> hashMap) {
UserUtil.hashMap = hashMap;
}
public static User getUserByUserId(Integer id) {
User user = hashMap.get(id);
System.out.println(user);
return user;
}
}
複製代碼
和 orElse 不一樣,它的參數接受一個lambda表達式
User user = Optional
.ofNullable(UserUtil.getUserByUserId(2))
.orElseGet(() -> new User(1, "Xiao Bai"));
複製代碼
同理,傳遞一個lambda表達式異常(注意啊,方法是限定了參數的,觸發異常就用orElseThrow,不能用orElseGet)
User user = Optional
.ofNullable(UserUtil.getUserByUserId(2))
.orElseThrow(()-> new AssertionError("AssertionError"));
複製代碼
調用map後,若是當前 Optional 爲 Optional.empty,則依舊返回 Optional.empty;不然返回一個新的 Optional,該 Optional 包含的是:函數 mapper 在以 value 做爲輸入時的輸出值
好比下面的例子,第一次調用map後,獲取的是name,傳遞給下一個map的值至關於Optional.ofNullable(name)
String user = Optional.ofNullable(UserUtil.getUserByUserId(1))
.map(user1 -> user1.name)
.map(String::toLowerCase)
.orElse("123");
System.out.println(user);
// 方法
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));
}
}
複製代碼
這個操做能夠用在對對象作屢次操做的場景下,而且保證爲空的時候返回指定的值,好比先獲取用戶的名稱,再獲取用戶的電話,作一下判斷後,再經過電話查詢到其它的數據,而後繼續...,最後若是某一環節出現異常,那就返回orElse定義的對象
flatMap 方法與 map 方法的區別在於,map 方法參數中的函數 mapper 輸出的是值,而後 map 方法會使用 Optional.ofNullable 將其包裝爲 Optional;而 flatMap 要求參數中的函數 mapper 輸出的就是 Optional
即 .flatMap(user -> Optional.of(user.name()))
都是差很少的套路,此次咱們先看源碼,能夠發現一樣是接受lambda表達式,而且要是一個Boolean返回值的,若是本次操做的optional是empty的,就返回自己
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
// 函數式接口部分代碼,能夠看到test是要求返回Boolean類型的
@FunctionalInterface
public interface Predicate<T> {
/** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */
boolean test(T t);
}
// 例子
String name = Optional.ofNullable(UserUtil.getUserByUserId(1))
.filter(user -> user.id == 2)
.map(user -> user.name)
.orElse("abc");
System.out.println(name);
複製代碼
經過觀察源碼,咱們能夠看到,不少爲空的都會返回empty,這讓各個操做都可以互相調用
Optional是一個比較簡單的類,推薦直接閱讀源碼,經過簡單的包裝,很優雅的解決的空指針問題,之前谷歌Guava庫就實現了,後面Java8正式把規範加到 java.util.Optional
類中。
另外,上面的作法是對於程序內的,若是是web開發,參數校驗,請使用Hibernate-Validator便可,做爲一個合格的後端,我不會讓前端挑刺的😀