Java 中可選的記錄參數
一、簡介
在本教程中,我們將討論使用Optional作為記錄參數的可能性以及為什麼這是一個不好的做法。
2. Optional用途
在討論Optional和記錄之間的關係之前,讓我們先快速回顧一下Java中Optional的預期用途。
通常,在 Java 8 之前,我們會使用null來表示物件的空狀態。但是,作為傳回值的null需要呼叫者程式碼在執行時進行null檢查驗證。如果呼叫者未驗證,則可能會收到NullPointerException 。獲取異常有時用於識別價值的缺失。
Optional的主要目標是表示一個方法傳回值,該值表示不存在值。我們可以使用Optional作為傳回值,而不是讓我們的應用程式因NullPointerException而崩潰來識別值的缺失。因此,我們在編譯時知道返回值包含某些內容或不包含任何內容。
此外,正如Java 文件中所說:
Optional 旨在為庫方法返回類型提供一種有限的機制,其中明確需要表示“無結果”,並且使用
null極有可能導致錯誤
因此,也必須注意Optional不打算做什麼。在這一點上,我們可以強調, Optional並不打算用作任何類別的實例字段。
3. Java 記錄的用例
我們也來看看有關記錄的一些概念,以便為使用Optional作為record參數打下更好的基礎。
記錄只是一個資料持有者。當我們想要將資料從一個地方傳輸到另一個地方(例如從資料庫到我們的應用程式)時,它非常適合。
讓我們解釋一下JEP-395 :
記錄是充當不可變資料的透明載體的類別。
記錄的一個關鍵定義是它們是不可變的。因此,一旦我們實例化一筆記錄,它的所有資料在程式的其餘部分中都保持不可修改。這對於傳輸資料的物件來說非常有用,因為不可變物件不太容易出錯。
記錄也會自動定義具有相同欄位名稱的存取器方法。因此,透過定義它們,我們可以得到與定義欄位相同的 getter。
JDK 記錄定義也建議記錄所保存的資料應該是透明的。因此,如果我們呼叫訪問器方法,我們應該獲得有效的資料。在這種情況下,有效資料意味著真正代表物件狀態的值。讓我們來解釋一下琥珀計劃:
資料類別(Record)的 API 對狀態、整個狀態以及除了狀態之外什麼都沒有建模。
不變性和透明度是捍衛記錄不得具有Optional參數這一論點的基本定義。
4. 可選作為記錄參數
現在我們對這兩個概念有了更好的理解,我們將了解為什麼必須避免使用Optional作為記錄參數。
首先,我們定義一個記錄範例:
public record Product(String name, double price, String description) {
}
我們已經為產品定義了一個資料持有者,其中包含name, price,和description.我們可以想像由資料庫查詢或 HTTP 呼叫產生的資料持有者。
現在,我們假設有時未設定產品描述。在這種情況下, description可以為空。解決這個問題的一種方法是將description欄位包裝到Optional物件中:
public record Product(String name, double price, Optional<String> description) {
}
儘管上面的程式碼編譯正確,但我們破壞了Product記錄的資料透明度。
此外,記錄不變性使得處理Optional實例比處理null變數更困難。讓我們透過一個簡單的測試來看看實際情況:
@Test
public void givenRecordCreationWithOptional_thenCreateItProperly() {
var emptyDescriptionProduct = new Product("television", 1699.99, Optional.empty());
Assertions.assertEquals("television", emptyDescriptionProduct.name());
Assertions.assertEquals(1699.99, emptyDescriptionProduct.price());
Assertions.assertNull(emptyDescriptionProduct.description().orElse(null));
}
我們創建了一個具有一些值的Product ,並使用產生的 getter 來斷言記錄實例化正確。
在我們的產品中,我們定義了變數name 、 price和description 。但是,由於description是Optional ,因此我們在檢索它後不會立即獲得值。我們需要做一些邏輯來打開它來取得值。換句話說,我們在呼叫訪問器方法後並沒有獲得正確的物件狀態。因此,它打破了Java記錄的資料透明度的定義。
我們可能會想,既然如此,我們該如何處理null呢?好吧,我們可以簡單地讓它們存在。 null表示物件的空狀態,在這種情況下比空的Optional實例更有意義。在這些場景中,我們可以透過使用@Nullable註解或其他處理null良好實踐來通知Product類別的使用者description可以為空。
由於記錄欄位是不可變的, description 字段無法更改。因此,要檢索description值,我們有一些選擇。一種是使用orElse () 和orElseGet()開啟它或傳回預設值。另一種方法是盲目地使用get() ,如果沒有值,它會拋出NoSuchElementException 。第三種是如果內部沒有任何內容,則使用orElseThrow()拋出錯誤。
在任何可能的處理方式中, Optional都沒有任何意義,因為在任何情況下,我們要么返回null要么拋出錯誤。讓description為可為空的String會比較簡單。
5. 結論
在本文中,我們了解了 Java 記錄的定義並了解了透明度和不變性的重要性。
我們也研究了Optional類的預期用途。更重要的是,我們討論了Optional不適合用來當作記錄參數。
與往常一樣,您可以在 GitHub 上找到原始程式碼。