Java8 Optional使用總結
阿新 • • 發佈:2022-03-26
Java8 Optional 總結
模型類樣例
@Data
private static class User {
private String name;
private String age;
}
用例1
@Test(expected = NoSuchElementException.class)
public void whenCreateEmptyOptional_thenNull() {
Optional<User> userOpt = Optional.empty();
userOpt.get();
}
獲取一個包含null的Optional物件
Optional<User> userOpt = Optional.empty()
optional 的get方法
// 這裡會丟擲NoSuchElementException(extends RuntimeException)
// 因為 userOpt 是一個包含null的Optional物件,因為是非受檢異常
// 最好在get之前 先檢查一下比如 呼叫 userOpt.ifPresent()
userOpt.get();
用例2
@Test(expected = NullPointerException.class) public void test2() { User user = null; Optional<User> userOptional = Optional.of(user); }
Optional 的靜態方法of 不能傳入null物件,否則報空指標異常,
看原始碼
/** * Optional 原始碼 */ public static <T> Optional<T> of(T value) { return new Optional<>(value); } private Optional(T value) { this.value = Objects.requireNonNull(value); } // Objects 原始碼 public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; }
用例3
@Test
public void test_ofNullable() {
User user = null;
Optional<User> userOptional = Optional.ofNullable(user);
}
Optional 靜態方法ofNullable可以傳入null,傳入null會得到一個包含null的optional物件
原始碼
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
用例4
@Test
public void test_getOptionalValue() {
String name = "jim";
Optional<String> nameOptional = Optional.of(name);
if (nameOptional.isPresent()) {
System.out.println(nameOptional.get());
}
}
Optional 例項方法 isPresent,判斷optional 的value是不是null
原始碼
public boolean isPresent() {
return value != null;
}
用例5
@Test
public void test_ifPresentFunc() {
String name = "jim";
Optional<String> nameOptional = Optional.of(name);
nameOptional.ifPresent(value -> System.out.println("ifPresent=>" + value));
}
ifPresent(Consumer consumer) :如果有值就執行一個consumer這個函式
原始碼
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
用例6
@Test
public void test_filter() {
String str = "abcd";
Optional<String> stringOptional = Optional.of(str);
stringOptional.filter(value -> value.contains("e"))
.ifPresent(value -> System.out.println("過濾後: " + value));
}
filter用於條件過濾,如果滿足傳入的Predicate函式,則返回this,不滿足返回一個包含null的Optional物件(既後續操作不做了,比如上面的ifPresent)
原始碼
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
用例7 map 用法
@Test
public void test_map() {
String str = "abcd";
Optional<String> stringOptional = Optional.of(str);
stringOptional.map(String::toUpperCase)
.ifPresent(value -> System.out.println("對映後: " + value));
}
map用於對映,將物件轉化成另一個物件,或者是對內容做變形(比如上面的將字串轉換為大寫),並返回一個Optional物件;如果呼叫map的Optional物件為空值Optional物件==,也會返回一個包含空值的Optional物件
用例8 flatMap用法
flatMap 和 map 的區別就是map自動幫你封裝成了Optional物件,而flatMap需要你自己手動封裝成Optional物件(這樣看來map更好用)
@Test
public void test_flatMap() {
String str = "abcd";
Optional<String> stringOptional = Optional.of(str);
stringOptional.flatMap(value -> Optional.ofNullable(value.toUpperCase()))
.ifPresent(value -> System.out.println("flatMap對映後: " + value));
}
用例9 orElse用法
@Test
public void test_orElse() {
String str = null;
Optional<String> stringOptional = Optional.ofNullable(str);
System.out.println(stringOptional.orElse("qwerty"));
}
orElse即當呼叫它的物件是value是null的Optional物件時就執行返回引數的物件引用的函式
相對於orElseGet的缺點是:
執行到orElse時,括號內的語句一定會先執行,可能會造成一定的浪費(比如是個大物件)
如果需要orElse中臨時建立物件,建議使用orElseGet,如果是已經建立好的物件的引用就無所謂了
原始碼(可以看到other進來的時候已經建立完畢,即使是個null的Optional物件)
public T orElse(T other) {
return value != null ? value : other;
}
用例10 orElseGet用法
@Test
public void test_orElseGet() {
String str = null;
Optional<String> stringOptional = Optional.ofNullable(str);
System.out.println(stringOptional.orElseGet(() -> "qwerty"));
}
原始碼
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
從原始碼可以看出來 只有value為null時,才會執行傳入進來的函式,
這樣當value不為null時,就可以避擴音前建立處物件所帶來的浪費了
用例11 orElseThrow
@Test
public void test_orElseThrow() {
String str = null;
Optional<String> stringOptional = Optional.ofNullable(str);
System.out.println(stringOptional.orElseThrow(RuntimeException::new));
}
orElseThrow 如果是null的Optional物件呼叫它,會丟擲括號內的異常(這個異常類必須要有無參建構函式)
原始碼
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}