Java 14 發布了,可以扔掉Lombok了?

2020-12-14 計算機java編程

2020年3月17日發布,Java正式發布了JDK 14 ,目前已經可以開放下載。在JDK 14中,共有16個新特性,本文主要來介紹其中的一個特性:JEP 359: Records

官方吐槽最為致命

早在2019年2月份,Java 語言架構師 Brian Goetz,曾經寫過一篇文章,詳盡的說明了並吐槽了Java語言,他和很多程式設計師一樣抱怨「Java太囉嗦」或有太多的「繁文縟節」,他提到:開發人員想要創建純數據載體類(plain data carriers)通常都必須編寫大量低價值、重複的、容易出錯的代碼。如:構造函數、getter/setter、equals()、hashCode()以及toString()等。

以至於很多人選擇使用IDE的功能來自動生成這些代碼。還有一些開發會選擇使用一些第三方類庫,如Lombok等來生成這些方法,從而會導致了令人吃驚的表現(surprising behavior)和糟糕的可調試性(poor debuggability)。

那麼,Brian Goetz 大神提到的純數據載體到底指的是什麼呢。他舉了一個簡單的例子:

這裡面的Piont其實就是一個純數據載體,他表示一個"點"中包含x坐標和y坐標,並且只提供了構造函數,以及一些equals、hashCode等方法。

於是,BrianGoetz大神提出一種想法,他提到,Java完全可以對於這種純數據載體通過另外一種方式表示。

其實在其他的面向對象語言中,早就針對這種純數據載體有單獨的定義了,如Scala中的case、Kotlin中的data以及C#中的record。這些定義,儘管在語義上有所不同,但是它們的共同點是類的部分或全部狀態可以直接在類頭中描述,並且這個類中只包含了純數據而已。

於是,他提出Java中是不是也可以通過如下方式定義一個純數據載體呢?

record Point(int x, int y){ }

神說要用record,於是就有了

就像大神吐槽的那樣,我們通常需要編寫大量代碼才能使類變得有用。如以下內容:

toString()方法hashCode() and equals()方法Getter 方法一個共有的構造函數對於這種簡單的類,這些方法通常是無聊的、重複的,而且是可以很容易地機械地生成的那種東西(ide通常提供這種功能)。

當你閱讀別人的代碼時,可能會更加頭大。例如,別人可能使用IDE生成的hashCode()和equals()來處理類的所有欄位,但是如何才能在不檢查實現的每一行的情況下確定他寫的對呢?如果在重構過程中添加了欄位而沒有重新生成方法,會發生什麼情況呢?

大神Brian Goetz提出了使用record定義一個純數據載體的想法,於是,Java 14 中便包含了一個新特性:EP 359: Records ,作者正是 Brian Goetz

Records的目標是擴展Java語言語法,Records為聲明類提供了一種緊湊的語法,用於創建一種類中是「欄位,只是欄位,除了欄位什麼都沒有」的類。通過對類做這樣的聲明,編譯器可以通過自動創建所有方法並讓所有欄位參與hashCode()等方法。這是JDK 14中的一個預覽特性。

一言不合反編譯

Records的用法比較簡單,和定義Java類一樣:

record Person (String firstName, String lastName) {}

如上,我們定義了一個Person記錄,其中包含兩個組件:firstName和lastName,以及一個空的類體。

那麼,這個東西看上去也是個語法糖,那他到底是怎麼實現的那?

我們先嘗試對他進行編譯,記得使用

--enable-preview

參數,因為records功能目前在JDK 14中還是一個預覽(preview)功能。

如前所述,Record只是一個類,其目的是保存和公開數據。讓我們看看用javap進行反編譯,將會得到以下代碼:

通過反編譯得到的類,我們可以得到以下信息:

1、生成了一個final類型的Person類(class),說明這個類不能再有子類了。

2、這個類繼承了java.lang.Record類,這個我們使用enum創建出來的枚舉都默認繼承java.lang.Enum有點類似

3、類中有兩個private final 類型的屬性。所以,record定義的類中的屬性都應該是private final類型的。

4、有一個public的構造函數,入參就是兩個主要的屬性。如果通過字節碼查看其方法體的話,其內容就是以下代碼,你一定很熟悉:

5、有兩個getter方法,分別叫做firstName和lastName。這和JavaBean中定義的命名方式有區別,或許大神想通過這種方式告訴我們record定義出來的並不是一個JavaBean吧。

6、還幫我們自動生成了toString(), hashCode() 和 equals()方法。值得一提的是,這三個方法依賴invokedynamic來動態調用包含隱式實現的適當方法。

還可以這樣玩

前面的例子中,我們簡單的創建了一個record,那麼,record中還能有其他的成員變量和方法嗎?我們來看下。

1、我們不能將實例欄位添加到record中。但是,我們可以添加靜態欄位。

2、我們可以定義靜態方法和實例方法,可以操作對象的狀態。

3、我們還可以添加構造函數。

所以,我們是可以在record中添加靜態欄位/方法的,但是問題是,我們應該這麼做嗎?

請記住,record推出背後的目標是使開發人員能夠將相關欄位作為單個不可變數據項組合在一起,而不需要編寫冗長的代碼。這意味著,每當您想要向您的記錄添加更多的欄位/方法時,請考慮是否應該使用完整的類來代替它。

總結

record 解決了使用類作為數據包裝器的一個常見問題。純數據類從幾行代碼顯著地簡化為一行代碼。

但是,record目前是一種預覽語言特性,這意味著,儘管它已經完全實現,但在JDK中還沒有標準化。

那麼問題來了,如果你用上了Java 14之後,你還會使用Lombok嗎?哦不,你可能短時間內都用不上,因為你可能Java 8都還沒用熟~

相關焦點

  • Java 14發布了,不使用"class"也能定義類了?還順手要幹掉Lombok!
    2020年3月17日發布,Java正式發布了JDK 14 ,目前已經可以開放下載。在JDK 14中,共有16個新特性,本文主要來介紹其中的一個特性:JEP 359: Records官方吐槽最為致命早在2019年2月份,Java 語言架構師 Brian Goetz,曾經寫過一篇文章(http://cr.openjdk.java.net/~briangoetz/amber/datum.html ),詳盡的說明了並吐槽了Java
  • 迷茫了,我們到底該不該用lombok?
    前言最近上網查資料發現很多人對lombok褒貶不一,引起了我的興趣,因為我們項目中也在大量使用lombok,大家不同的觀點讓我也困惑了幾天,今天結合我實際的項目經驗,說說我的個人建議。隨便搜搜就找到了這幾篇文章:這些人建議使用 lombok,覺得它是一個神器,可以大大提高編碼效率,並且讓代碼更優雅。
  • Lombok的@Builder不好使?來試試這個
    以下文章來源於苦味代碼 ,作者L相信Lombok插件大家一定不會陌生,一個常用的註解是:@Builer, 它可以幫我們快速實現一個builder模式。試試SuperBuilder吧這個問題在lombokv1.18.2版本之前其實很難辦,但是在這個版本官方引入了一個新的註解@SuperBuilder,無法build父類的問題迎刃而解The @SuperBuilder annotation produces complex builder APIs for your classes.
  • 記一次使用 Lombok 造成的事故!
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫序言去年在項目當中引入了Lombok插件,著實解放了雙手,代替了一些重複的簡單工作(Getter,Setter,toString等方法的編寫
  • Java14發布!不使用"class"也能定義類了?還順手要幹掉Lombok!
    作者:HollisChuang 來源:掘金 連結:https://juejin.im/post/5e7421b8518825497468178a2020年3月17日發布,Java正式發布了JDK 14 ,目前已經可以開放下載。
  • Java 15 即將到來,新特性速覽!
    此功能正在 JDK 14 中進入較早的孵化器階段,JDK 15 中提供了改進。密封類的預覽版。密封類與接口一起限制其他類或接口可以擴展或實現它們。此功能的目標包括允許類或接口的開發者控制負責實現該代碼,提供比訪問修飾符更具聲明性的方式來限制超類的使用,以及通過支持詳盡的內容來支持模式匹配的未來方向。
  • JDK/JAVA 13正式版發布
    JEP 353,Reimplement the Legacy Socket API:使用易於維護和調試的更簡單、更現代的實現替換java.net.Socket和java.net.ServerSocket API使用的底層實現。
  • 動力節點Java學院2021年Java學習路線圖最新出爐啦
    動力節點深知同學們的學習困難,為此整理了一套最新的2021年新版學習路線圖,增加了目前企業最新應用技術,這套學習路線圖,只要你完成一半基本就可以找到很不錯的工作了,如果想要獲得高薪,那就努力學完它吧!第一階段:Javase基礎
  • getty 發布,一個完全基於 java 實現的 aio 框架
    AIO的發布使得實現一套網絡通訊框架變得相對簡單。但如果你不努力,可能也無法理解哦。3、本人對netty比較喜歡,無論是其性能還是編程思想(JBOSS提供的一個java開源網絡框架,可以說是java網絡通訊裡的一哥,極其穩定和強大的性能使得被廣泛使用)4、有了netty為何還要自己造輪子?這裡有兩個原因,其一是本人就喜歡造輪子,這是病,改不了。
  • JAVA基礎學習|JAVA中的包總結!
    4.java.net包。  該包提供實現網絡應用與開發的類。  5.java.sql包。  該包提供了使用Java語言訪問並處理存儲在數據源(通常是一個關係型資料庫)中的數據API。  6.java.awt包
  • 跟我學java編程—Java的Scanner類
    可以通過Scanner類方便地獲取用戶輸入。通過Scanner類獲取用戶輸入時,控制臺會一直等待用戶的輸入,直到用戶敲回車鍵結束,把所輸入的內容傳給Scanner,程序要從Scanner獲取輸入的內容,則只需要調用Scanner的nextLine()方法即可。
  • 你必須掌握的 21 個 Java 核心技術!
    JVM作為java運行的基礎,很難相信對於JVM一點都不了解的人可以把java語言吃得很透。我在面試有超過3年Java經驗的開發者的時候, JVM幾乎就是一個必問的問題了。當然JVM不是唯一決定技術能力好壞的面試問題,但是可以佐證java開發能力的高低。
  • java是什麼文件格式?.java文件怎麼打開?
    java是什麼文件?  Java文件是由Sun Microsystems公司於1995年5月推出的Java程序設計語言和Java平臺的總稱。用Java實現的HotJava瀏覽器(支持Java applet)顯示了Java的魅力:跨平臺、動態的Web、Internet計算。從此,Java被廣泛接受並推動了Web的迅速發展,常用的瀏覽器現在均支持Java applet。
  • Java HeartBeat 0.4 發布,應用伺服器心跳檢測
    HeartBeat 0.4 發布, 該版本的主要更新如下
  • 跟我學java編程—認識java的整數類型
    整型變量可按如下方式聲明:在一條語句中,可以聲明多個同一類型的整型變量,每個變量之間用英文逗號分隔:整型變量可按如下方式初始化:在初始化變量或為變量賦值時,常常會用到一些數值,這些值通常稱為常量。Java語言中整型常量有三種不同的表示形式:十進位、八進位和十六進位。
  • 好程式設計師Java培訓分享Java讀寫Properties配置文件
    2.Properties中的主要方法 (1)load(InputStream inStream) 這個方法可以從
  • Java基礎學習:一篇文章讓你搞懂Java字符串的前世今生
    .#22// java/lang/Object."可以看到,還是沒有真正的【拼接】操作發生,final 意味著 x 的值不可改變,因此其它引用 x 的地方都可以安全地被替換為 "b",而不用擔心 x 被改變,從源碼編譯為字節碼時,javac 就也進行了優化,把所有出現 x 的地方都替換成為了 "b"那麼,什麼是真正的【拼接】操作呢?
  • JAVA 基礎:JAVA開發環境搭建
    打開Path變量,在變量值最前加入 %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;(方法同上)4.驗證:運行cmd,輸入java -version,顯示java版本則成功。或使用 vi /etc/profile 命令,將上面的代碼,拷貝到 profile文件中,輸入:shift+I 快捷鍵 ,輸入完成 按esc 退出編輯模式,保存並退出 shift+: 鍵,輸入wq5.使用source命令更新配置文件 : source /etc/profile6.輸入java
  • 如何在Windows10系統中配置java的JDK環境
    今天給大家分享一下如何在Windows10系統中配置java的JDK環境。截圖如下:14.點擊」確定「按鈕後,用戶變量下面會顯示剛剛新增的「JVAV_HOME」欄位。可以進行java編程了,在 E:\test 路徑下面新建一個 Test.java 文件,截圖如下:22.在Test.java文件中輸入Java代碼程序:class Test{public static void main(String[] args){