更新時(shí)間:2022-09-08 11:42:21 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1625次
在本教程中,我們將快速瀏覽 Java 8 中一些最有趣的新特性。
我們將討論接口默認(rèn)和靜態(tài)方法、方法引用和可選。
在 Java 8 之前,接口只能有公共抽象方法。如果不強(qiáng)制所有實(shí)現(xiàn)類創(chuàng)建新方法的實(shí)現(xiàn),就不可能向現(xiàn)有接口添加新功能,也不可能創(chuàng)建帶有實(shí)現(xiàn)的接口方法。
從 Java 8 開始,接口可以具有靜態(tài)和默認(rèn)方法,盡管在接口中聲明了這些方法,但它們具有已定義的行為。
1.靜態(tài)方法
考慮接口的這個(gè)方法(我們稱這個(gè)接口Vehicle):
static String producer() {
return "N&F Vehicles";
}
靜態(tài)producer()方法只能通過接口和在接口內(nèi)部使用。它不能被實(shí)現(xiàn)類覆蓋。
要在接口外調(diào)用它,應(yīng)使用靜態(tài)方法調(diào)用的標(biāo)準(zhǔn)方法:
String producer = Vehicle.producer();
2.默認(rèn)方法
默認(rèn)方法是使用新的default關(guān)鍵字聲明的。這些可以通過實(shí)現(xiàn)類的實(shí)例訪問,并且可以被覆蓋。
讓我們?yōu)閂ehicle接口添加一個(gè)默認(rèn)方法,該方法也會(huì)調(diào)用該接口的靜態(tài)方法:
default String getOverview() {
return "ATV made by " + producer();
}
假設(shè)這個(gè)接口是由類VehicleImpl實(shí)現(xiàn)的。
為了執(zhí)行默認(rèn)方法,應(yīng)該創(chuàng)建這個(gè)類的一個(gè)實(shí)例:
Vehicle vehicle = new VehicleImpl();
String overview = vehicle.getOverview();
方法引用可用作僅調(diào)用現(xiàn)有方法的 lambda 表達(dá)式的更短且更易讀的替代方案。方法引用有四種變體。
1.引用靜態(tài)方法
對(duì)靜態(tài)方法的引用包含語法ContainingClass::methodName。
我們將嘗試在Stream API 的幫助下計(jì)算List<String>中的所有空字符串:
boolean isReal = list.stream().anyMatch(u -> User.isRealUser(u));
讓我們仔細(xì)看看anyMatch()方法中的 lambda 表達(dá)式。它只是調(diào)用User類的靜態(tài)方法isRealUser(User user)
因此,它可以用對(duì)靜態(tài)方法的引用代替:
boolean isReal = list.stream().anyMatch(User::isRealUser);
這種類型的代碼看起來信息量更大。
2.引用實(shí)例方法
對(duì)實(shí)例方法的引用包含語法containsInstance::methodName。
以下代碼調(diào)用User類型的isLegalName(String string)方法,該方法驗(yàn)證輸入?yún)?shù):
User user = new User();
boolean isLegalName = list.stream().anyMatch(user::isLegalName);
3.引用特定類型對(duì)象的實(shí)例方法
此引用方法采用語法ContainingType::methodName。
讓我們看一個(gè)例子:
long count = list.stream().filter(String::isEmpty).count();
4.對(duì)構(gòu)造函數(shù)的引用
對(duì)構(gòu)造函數(shù)的引用采用語法ClassName::new。
由于 Java 中的構(gòu)造函數(shù)是一種特殊的方法,因此方法引用也可以應(yīng)用到它,借助new 作為方法名稱:
Stream<User> stream = list.stream().map(User::new);
在 Java 8 之前,開發(fā)人員必須仔細(xì)驗(yàn)證他們引用的值,因?yàn)榭赡軙?huì)拋出NullPointerException (NPE)。所有這些檢查都需要非常煩人且容易出錯(cuò)的樣板代碼。
Java 8 Optional<T>類可以幫助處理有可能獲得NPE的情況。它用作T類型對(duì)象的容器。如果此值不是null ,它可以返回此對(duì)象的值。當(dāng)此容器內(nèi)的值為null時(shí),它允許執(zhí)行一些預(yù)定義的操作,而不是拋出NPE。
1.創(chuàng)建可選<T>
Java8Optional類的實(shí)例可以在其靜態(tài)方法的幫助下創(chuàng)建。
讓我們看看如何返回一個(gè)空的Optional:
Optional<String> optional = Optional.empty();
接下來,我們返回一個(gè)包含非空值的Optional :
String str = "value";
Optional<String> optional = Optional.of(str);
最后,如果參數(shù)為null ,則返回具有特定值的Optional或空Optional的方法如下:
Optional<String> optional = Optional.ofNullable(getString());
2.可選<T>用法
假設(shè)我們希望得到一個(gè)List<String>,在null的情況下,我們想用一個(gè)新的ArrayList<String>實(shí)例來替換它。
對(duì)于 Java 8 之前的代碼,我們需要執(zhí)行以下操作:
List<String> list = getList();
List<String> listOpt = list != null ? list : new ArrayList<>();
使用 Java 8,可以使用更短的代碼實(shí)現(xiàn)相同的功能:
List<String> listOpt = getList().orElseGet(() -> new ArrayList<>());
當(dāng)我們需要以舊方式訪問某個(gè)對(duì)象的字段時(shí),甚至還有更多樣板代碼。
假設(shè)我們有一個(gè)User類型的對(duì)象,它有一個(gè)Address類型的字段和一個(gè)String類型的字段 s treet ,如果存在,我們需要返回street字段的值,如果street為null ,我們需要返回默認(rèn)值:
User user = getUser();
if (user != null) {
Address address = user.getAddress();
if (address != null) {
String street = address.getStreet();
if (street != null) {
return street;
}
}
}
return "not specified";
這可以用Optional來簡(jiǎn)化:
Optional<User> user = Optional.ofNullable(getUser());
String result = user
.map(User::getAddress)
.map(Address::getStreet)
.orElse("not specified");
在此示例中,我們使用map()方法將調(diào)用getAdress()的結(jié)果轉(zhuǎn)換為Optional<Address>和getStreet()轉(zhuǎn)換為Optional<String>。如果這些方法中的任何一個(gè)返回null,則map()方法將返回一個(gè)空Optional。
現(xiàn)在想象我們的 getter 返回Optional<T>。
在這種情況下,我們應(yīng)該使用flatMap()方法而不是map():
Optional<OptionalUser> optionalUser = Optional.ofNullable(getOptionalUser());
String result = optionalUser
.flatMap(OptionalUser::getAddress)
.flatMap(OptionalAddress::getStreet)
.orElse("not specified");
Optional的另一個(gè)用例是更改NPE,但有另一個(gè)例外。
所以,就像我們之前所做的那樣,讓我們??嘗試以 Java 8 之前的風(fēng)格來做這件事:
String value = null;
String result = "";
try {
result = value.toUpperCase();
} catch (NullPointerException exception) {
throw new CustomException();
}
如果我們使用Optional <String>,答案會(huì)更易讀、更簡(jiǎn)單:
String value = null;
Optional<String> valueOpt = Optional.ofNullable(value);
String result = valueOpt.orElseThrow(CustomException::new).toUpperCase();
以上就是關(guān)于“Java1.8新特性介紹”,如果大家想了解更多相關(guān)知識(shí),不妨來關(guān)注一下動(dòng)力節(jié)點(diǎn)Java視頻教程,里面的課程內(nèi)容從入門到精通,細(xì)致全面,通俗易懂,適合沒有基礎(chǔ)的小伙伴學(xué)習(xí),希望對(duì)大家能夠有所幫助。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)