Java Optional介紹與使用方法
Optional是Java 8推出時加入的新功能,Optional被發明出來的初衷是為了解決Java常見的NullPointException。
為沒寫過Java的人科普一下,NullPointException大多數的發生原因都是針對value為Null進行操作而導致的例外狀況,Optional為此出現。
Java 8 Optional 使用方式
使用方式很簡單,可以理解為將值外部再包了一層類別,比方說以下程式:
1 | |
Student類別的外部包了一個Optional類別,可以想像為程式外部又包了一個try catch的處理。
Optioal常用的方法如下:
- isPresent() 判斷是否為Null,是則回傳True,否則回傳False
- get() 取得Optional內的值,需要先使用isPresent()確認是否為Null
- Optional.of() 建立Optional的方法,若為Null會直接報錯
- Optional.ofNullable() 建立Optional的方法,可以放入Null與非Null物件
- ifPresent() 如果值為非Null就執行某方法,沒有回傳值
- orElse() 如果值為Null就用參數代替
- orElseGet() 如果值為Null就執行該方法,與orElse()相差在可接受傳入參數不同
- orElseThrow() 如果值為Null就拋出某些Exception
以下介紹一些常用的方法
1 | |
更多實際應用
使用Optional還有一個好處,就是可以套用Java 8 的API
- 判斷是否為2016年
1 | |
- 判斷物件價格範圍是否介於15~20之間
1 | |
- 先處理過再判斷。
1 | |
- 取得陣列長度,null為0
1 | |
- map 與 flatmap 的差異
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 假設我們有一個包含字串的列表
List<String> words = Arrays.asList("Java", "Stream", "API");
// 使用map操作,將每個字串轉換為它的長度
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println("使用 map 操作得到的長度列表: " + wordLengths);
// 使用flatMap操作,將每個字串拆分為單個字符並平坦化為單獨的流
List<Character> characters = words.stream()
.flatMap(word -> word.chars().mapToObj(c -> (char) c))
.collect(Collectors.toList());
System.out.println("使用 flatMap 操作得到的字符列表: " + characters);
/ /使用 map 操作得到的長度列表: [4, 6, 3]
// 使用 flatMap 操作得到的字符列表: [J, a, v, a, S, t, r, e, a, m, A, P, I]
- 參考用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59// 取得第一個非null的值,Optional::get 是為了取得<Stream<String>>
// 方法會全數執行
String found = Stream.of(getEmpty(), getHello(), getBye())
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst()
.get();
// 同樣意思,但方法不會全數執行
Optional<String> found2 =
Stream.<Supplier<Optional<String>>>of(this::getEmpty, this::getHello, this::getBye)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
// 若function想要帶上參數 需使用lambda
Optional<String> found3 = Stream.<Supplier<Optional<String>>>of(
() -> createOptional("empty"),
() -> createOptional("hello")
)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
// 判斷是否全數為null
String found4 = Stream.<Supplier<Optional<String>>>of(
() -> createOptional("empty"),
() -> createOptional("E")
)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst()
.orElseGet(() -> "default");
assertEquals("E",found4);
private Optional<String> getEmpty() {
return Optional.empty();
}
private Optional<String> getHello() {
return Optional.of("hello");
}
private Optional<String> getBye() {
return Optional.of("bye");
}
private Optional<String> createOptional(String input) {
if (input == null || "".equals(input) || "empty".equals(input)) {
return Optional.empty();
}
return Optional.of(input);
} - map與flatmap以上就是常見的基本Optional用法,也許不需要全部都會,只需要基本了解就很夠用了也說不定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public static String testOptionalFlatMap(Student student) {
// 這段是使用Optional 檢測 Null
var score = student.getScore();
if(score.isPresent()) {
var word = score.get().getWord();
if(word .isPresent()) {
return word.get();
}
}
return "NA";
// 這段是使用Optional Flatmap 檢測 Null
return student.getScore()
.flatMap(Score::getWord)
.orElse("n.a.");
}
以上
Java Optional介紹與使用方法
https://clark1945.github.io/2024/04/24/Java-Optional介紹與使用方法/