這篇文章主要講解了“如何使用Java Optional類(lèi)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“如何使用Java Optional類(lèi)”吧!
成都創(chuàng)新互聯(lián)公司從2013年開(kāi)始,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元青銅峽做網(wǎng)站,已為上家服務(wù),為青銅峽各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:13518219792注意:示例代碼要求使用Java 11及更高版本。所有代碼在 Vavr0.10.2環(huán)境下完成測(cè)試。
Java Optional 簡(jiǎn)介
Optional 并不是什么新概念,像 Haskell、Scala 這樣的函數(shù)式編程語(yǔ)言已經(jīng)提供了實(shí)現(xiàn)。調(diào)用方法后,返回值未知或者不存在(比如 null)的情況下,用 Optional 處理非常好用。下面通過(guò)實(shí)例進(jìn)行介紹。
新建 Optional 實(shí)例
首先,需要獲得 Optional 實(shí)例,有以下幾種方法可以新建 Optional 實(shí)例。不僅如此,還可以創(chuàng)建empty Optional。方法一,通過(guò) value 創(chuàng)建,過(guò)程非常簡(jiǎn)單:
Optional<Integer> four = Optional.of(Integer.valueOf(4));
if (four.isPresent){
System.out.println("Hoorayy! We have a value");
}
else {
System.out.println("No value");
}
為Integer 4 新建一個(gè)Optional實(shí)例。這種方法得到的 Optional 始終包含一個(gè) value 且不為 null,例如上面這個(gè)示例。使用 ifPresent() 可以檢查value是否存在。可以注意到 four 不是 Integer,而是一個(gè)裝有整數(shù)的容器。如果確認(rèn) value 存在,可以用 get() 方法執(zhí)行拆箱操作。具有諷刺意味的是,調(diào)用 get() 前如果不進(jìn)行檢查,可能會(huì)拋出 NoSuchElementException。
方法二,得到 Optional 對(duì)象的另一種方法是使用 stream。Stream提供的一些方法會(huì)返回Optional,可以用來(lái)檢查結(jié)果是否存在,例如:
findAny
findFirst
max
min
reduce
查看下面的代碼段:
Optional<Car> car = cars.stream().filter(car->car.getId().equalsIgnoreCase(id)).findFirst();
方法三,使用 Nullable 新建 Optional??赡墚a(chǎn)生 null:
Optional<Integer> nullable = Optional.ofNullable(client.getRequestData());
最后,可以新建一個(gè) empty Optional:
Optional<Integer> nothing = Optional.empty();
如何使用 Optional
獲得 Optional 對(duì)象后即可使用。一種典型的場(chǎng)景是在 Spring 倉(cāng)庫(kù)中根據(jù) Id 查找記錄??梢允褂?Optional 實(shí)現(xiàn)代碼邏輯,避免 null 檢查(順便提一下,Spring 也支持 Vavr Option)。比如,從圖書(shū)倉(cāng)庫(kù)里查找一本書(shū)。
Optional<Book> book = repository.findOne("some id");
首先,如果有這本書(shū),可以繼續(xù)執(zhí)行對(duì)應(yīng)的業(yè)務(wù)邏輯。在前面的章節(jié)用 if-else實(shí)現(xiàn)了功能。當(dāng)然,還有其他辦法:Optional 提供了一個(gè)方法,接收 Consumer 對(duì)象作為輸入:
repository.findOne("some id").ifPresent(book -> System.out.println(book));
還可以直接使用方法引用,看起來(lái)更簡(jiǎn)單:
repository.findOne("some id").ifPresent(System.out::println);
如果倉(cāng)庫(kù)中沒(méi)有該書(shū),可以用ifPresentOrElseGet提供回調(diào)函數(shù):
repository.findOne("some id").ifPresentOrElseGet(book->{
// 如果 value 存在
}, ()->{
// 如果 value 不存在
});
如果結(jié)果不存在,可以返回另一個(gè)value:
Book result = repository.findOne("some id").orElse(defaultBook);
但是,Optional 也有缺點(diǎn),使用時(shí)需要注意。最后一個(gè)例子中,“確?!睙o(wú)論如何都能獲得一本書(shū),可能在倉(cāng)庫(kù)中,也可能來(lái)自 orElse。但如果默認(rèn)的返回值不是常量或者需要支持一些復(fù)雜方法該怎么辦?首先,Java 無(wú)論如何都會(huì)執(zhí)行 findOne,然后調(diào)用 orElse方法。默認(rèn)返回值可以為常量,但正如我之前所說(shuō)那樣,執(zhí)行過(guò)程比較耗時(shí)。
另一個(gè)示例
下面用一個(gè)簡(jiǎn)單的示例介紹如何實(shí)際使用 Optional 和 Option 類(lèi)。有一個(gè) CarRepository,可以根據(jù)提供的 ID(比如車(chē)牌號(hào))查找汽車(chē),接下來(lái)用這個(gè)示例介紹如何使用 Optional 和 Option。
首先,加入下面代碼
從 POJO 類(lèi) Car 開(kāi)始。它遵循 immutable 模式,所有字段都標(biāo)記為 final,只包含 getter 沒(méi)有 setter。初始化時(shí)提供所有數(shù)據(jù):
public class Car {
private final String name;
private final String id;
private final String color;
public Car (String name, String id, String color){
this.name = name;
this.id = id;
this.color = color;
}
public String
getId(){
return id;
}
public String
getColor() {
return color;
}
public String
getName() {
return name;
}
@Override
public String
toString() {
return "Car "+name+" with license id "+id+" and of color "+color;
}
}
接下來(lái)創(chuàng)建 CarRepository類(lèi)。提供兩種方法根據(jù)Id查找汽車(chē):一種是老辦法,使用 Optional。和之前在 Spring 倉(cāng)庫(kù)的做法類(lèi)似,結(jié)果可能為 null。
publicclass CarRepository {
private List<Car> cars;
public CarRepository(){
getSomeCars();
}
Car
findCarById(String id){
for (Car car: cars){function(){ //外匯跟單www.gendan5.com if (car.getId().equalsIgnoreCase(id)){
return car;
}
}
return null;
}
Optional<Car> findCarByIdWithOptional(String id){
return cars.stream().filter(car->car.getId().equalsIgnoreCase(id)).findFirst();
}
private void getSomeCars(){
cars = new ArrayList<>();
cars.add(new Car("tesla", "1A9 4321", "red"));
cars.add(new Car("volkswagen", "2B1 1292", "blue"));
cars.add(new Car("skoda", "5C9 9984", "green"));
cars.add(new Car("audi", "8E4 4321", "silver"));
cars.add(new Car("mercedes", "3B4 5555", "black"));
cars.add(new Car("seat", "6U5 3123", "white"));
}
}
注意:初始化過(guò)程會(huì)在倉(cāng)庫(kù)中添加一些汽車(chē)模擬數(shù)據(jù),便于演示。為了突出重點(diǎn),避免問(wèn)題復(fù)雜化,下面的討論專(zhuān)注于 Optional 和 Option。
使用Java Optional
使用JUnit創(chuàng)建一個(gè)新測(cè)試:
@Test
void getCarById(){
Car car = repository.findCarById("1A9 4321");
Assertions.assertNotNull(car);
Car nullCar = repository.findCarById("M 432 KT");
Assertions.assertThrows(NullPointerException.class, ()->{
if (nullCar == null){
throw new NullPointerException();
}
});
}
上面的代碼段采用了之前的老辦法。查找捷克牌照1A9 4321對(duì)應(yīng)的汽車(chē),檢查該車(chē)是否存在。輸入俄羅斯車(chē)牌找不到對(duì)應(yīng)的汽車(chē),因?yàn)閭}(cāng)庫(kù)中只有捷克車(chē)。結(jié)果為 null 可能會(huì)拋出 NullPointerException。
接下來(lái)用Java Optional。第一步,獲得 Optional 實(shí)例,從存儲(chǔ)庫(kù)中使用指定方法返回 Optional:
@Test
void getCarByIdWithOptional(){
Optional<Car> tesla = repository.findCarByIdWithOptional("1A9 4321");
tesla.ifPresent(System.out::println);
}
這時(shí)調(diào)用findCarByIdWithOptional方法打印車(chē)輛信息(如果有的話)。運(yùn)行程序,得到以下結(jié)果:
Car tesla with license id 1A9 4321 and of color red
但是,如果代碼中沒(méi)有特定方法該怎么辦?這種情況可以從方法返回可能包含 null 的 Optional,稱為nullable。
Optional<Car> nothing = Optional.ofNullable(repository.findCarById("5T1 0965"));
Assertions.assertThrows(NoSuchElementException.class, ()->{
Car car = nothing.orElseThrow(()->new NoSuchElementException());
});
上面這段代碼段中,我們發(fā)現(xiàn)了另一種方法。通過(guò) findCarById 創(chuàng)建 Optional,如果未找到汽車(chē)可以返回 null。沒(méi)有找到車(chē)牌號(hào)5T1 0965汽車(chē)時(shí),可以用 orElseThrow 手動(dòng)拋出 NoSuchElementException。另一種情況,如果請(qǐng)求的數(shù)據(jù)不在倉(cāng)庫(kù)中,可以用orElse返回默認(rèn)值:
Car audi = repository.findCarByIdWithOptional("8E4 4311")
.orElse(new Car("audi",
"1W3 4212",
"yellow"));
if (audi.getColor().equalsIgnoreCase("silver")){
System.out.println("We have silver audi in garage!");
}
else {
System.out.println("Sorry, there is no silver audi, but we called you a taxi");
}
好的,車(chē)庫(kù)里沒(méi)有找到銀色奧迪,只好打車(chē)了!
使用 Vavr Option
Vavr OptionOption提供了另一種解決辦法。首先,在項(xiàng)目中添加依賴,(使用 Maven)安裝 Vavr:
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.10.2</version>
</dependency>
簡(jiǎn)而言之,Vavr 提供了類(lèi)似的 API 新建 Option 實(shí)例。可以從 nullable 新建 Option 實(shí)例,像下面這樣:
Option<Car> nothing = Option.of(repository.findCarById("T 543 KK"));
也可以用 none 靜態(tài)方法創(chuàng)建一個(gè)empty容器:
Option<Car> nullable = Option.none();
此外,還有一種方法可以用 Java Optional 新建 Option??聪旅孢@段代碼:
Option<Car> result = Option.ofOptional(repository.findCarByIdWithOptional("5C9 9984"));
使用 Vavr Option,可以使用與 Optional相同的 API 來(lái)完成上述任務(wù)。例如,設(shè)置默認(rèn)值:
Option<Car> result = Option.ofOptional(repository.findCarByIdWithOptional("5C9 9984"));
Car skoda = result.getOrElse(new Car("skoda",
"5E2 4232",
"pink"));
System.out.println(skoda);
或者,請(qǐng)求的數(shù)據(jù)不存在時(shí)可以拋出異常:
Option<Car> nullable = Option.none();
Assertions.assertThrows(NoSuchElementException.class, ()->{
nullable.getOrElseThrow(()->new NoSuchElementException());
});
另外,當(dāng)數(shù)據(jù)不可用時(shí),可以執(zhí)行以下操作:
nullable.onEmpty(()->{
///runnable
});
如何根據(jù)數(shù)據(jù)是否存在來(lái)執(zhí)行相應(yīng)操作,類(lèi)似 Optional 中 ifPresent?有幾種實(shí)現(xiàn)方式。與 Optional 中 isPresent 類(lèi)似,在 Option 中對(duì)應(yīng)的方法稱為 isDefined:
if (result.isDefined()){
// 實(shí)現(xiàn)功能
}
然而,使用 Option能擺脫 if-else。是否可以用Optional相同的方式完成?使用 peek 操作:
result.peek(val -> System.out.println(val)).onEmpty(() -> System.out.println("Result is missed"));
此外,Vavr Option還提供了一些其他非常有用的方法,在函數(shù)式編程上比Optional類(lèi)效果更好。因此,建議您花一些時(shí)間來(lái)探索 Vavr Option javadocs嘗試使用這些API。我會(huì)持續(xù)跟進(jìn)一些類(lèi)似 map、narrow、isLazy 和 when 這樣有趣的功能。
感謝各位的閱讀,以上就是“如何使用Java Optional類(lèi)”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)如何使用Java Optional類(lèi)這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
網(wǎng)頁(yè)標(biāo)題:如何使用JavaOptional類(lèi)-創(chuàng)新互聯(lián)
URL地址:http://www.rwnh.cn/article38/hdppp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、網(wǎng)站制作、定制網(wǎng)站、響應(yīng)式網(wǎng)站、微信公眾號(hào)、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容