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