在歷經三個年頭,Java從上個長期支援版本(Long Term Support, LTS)的Java 11,來到了新的Java 17 LTS,版本更新之際,LTS釋出週期、免費授權的改變,以及對設計有重大影響的新語法特性,都是值得留意之處。

變更LTS釋出週期與授權

2021年9月14日,Java迎來版號17的LTS新版本,距離上個LTS的Java 11(2018年9月)為時三年,這是因為從Java 9開始,JDK採取以半年為週期,常態化發布新版本的做法,其中Java 9、12到16為短期支援版本,釋出後六個月後就不再維護,而長期支援版本每三年釋出一次,目前有Java 11與17,實際維護時間視JDK來源而定,可能是三到六年不等。

企業基於臭蟲、安全修正等穩定性考量,多半只採用LTS,然而從Java 11到17,這中間的版本仍有些不錯的特性,為了讓企業有更多的LTS選擇,從Java 17開始,LTS的釋出週期,加速為每兩年一次。考量穩定性的不只是企業,開放原始碼程式庫或框架也會基於LTS來開發、發布重大版本。

以Spring為例,其Spring框架6與Spring Boot 3,至少要基於Java 17(以及Jakarta EE 9),至於Spring 5.3.x及Spring Boot 2.x,則有相容於Java 17的版本,相關細節可見〈A Java 17 and Jakarta EE 9 baseline for Spring Framework 6〉;Hibernate則更為積極,從舊版本的5.3起,都建立了相容於Java 17的目標,相關細節可見〈Hibernate: all systems go for Java 17〉

眾所皆知,自Sun被Oracle收購之後,Oracle積極主張Oracle JDK在商業使用或特定用途必須支付授權費用,這導致了後續Java社群、各大廠商推出了可合法(免費)使用的JDK建構版本(可參考先前專欄〈Java依舊免費?〉)。

然而,歷經Java 8到Java 16這些版本之後,Oracle宣稱其聽取社群意見,認為社群依舊想從可信任來源取得JDK建構,因而推出了新的免費授權(包括商用),他們表示,Java 17以後,到新的LTS發布後一年,都可採用免費授權,當然,免費並不代表不用留意授權內容,詳情可參考〈Introducing the Free Java License〉

語法方面的簡化

Java採每六個月頻繁釋出新版本,以突顯Java的積極活躍,也讓一些對新特性感興趣的開發者,可以在頻繁釋出的新版本中評估,或採用新特性,甚至從Java 12開始,有些Java新功能未正式定案前,為了取得開發者的意見回饋,會以預覽形式發布(透過--enable-preview開啟)。

然而,如果是僅關注LTS的開發者,可能會搞不太清楚,哪個版本中可以使用哪些新功能,特別是那些與撰寫程式直接相關的新語法;既然Java 17已經正式釋出,那麼Java究竟有哪些新的突破?

簡而言之,這段日子以來,Java不斷地從其他的語言,特別是Scala、Kotlin、C#中吸取經驗,並融合了本身既有語法、典範等考量而推出新語法,就我的看法而言,主要就是分為兩種類型:一是簡化程式撰寫的語法,二是會影響設計風格的語法。

在簡化程式撰寫的語法方面比較單純,目的無非是致力於避免Java語法囉嗦,甚至導致程式碼難以閱讀的惡名。

就正式釋出的Java版本而言,這類新特性包含Java 11的var增強,可在更多場合自動推斷變數型態。

相較之下,Java 14的switch表示式,在需要透過switch來計算值,或者預設不要自動fall through的場合時,可用來簡化程式撰寫等。

對於經常設計樣版(像是HTML、SQL、JSON、XML等)的開發者而言,Java 15的文字區塊(Text Block)應該是最有用的簡化特性,透過"""來含括的文字區塊,就算是換行,也會是字串的一部份,其中更方便的是,結尾"""的縮排位置,決定了區塊中的每行字串縮排之依據,而不像其他語言,直接以行首來作為每行字串的開始。

會影響設計的語法

var、switch表示式、文字區塊這類語法簡化,有當然是很好,沒有的話,說實在地,也不會對設計產生什麼重大影響,充其量就是程式寫起來囉嗦、可讀性不佳罷了;然而,Java 16、17正式釋出的新特性,像是Java 16的模式比對(Pattern match)、記錄類別(Record class),以及Java 17的彌封類別(sealed class),都對設計風格會產生重大的影響。

Java 16的instanceof模式比對(Pattern match),以及Java 17中為預覽特性的switch模式比對,就目前來說,還是算簡化程式撰寫方面的特性,因為模式比對的對象目前仍限於型態比對,不過,就JEP 405來看,未來會繼續增強,令其具備解構模式的功能。

就記錄類別而言,從表面上來看,這就像是POJO(Plain Ordinary Java Object)、JavaBean的替代品、hashCode、equals、toString自動生成的語法糖,或者是作為一個更有效率的資料載體,實際上不只是如此。例如,方才提到的POJO、JavaBean、資料載體等,各自都代表著另一種封裝意圖;彌封類別也是,表面上看來,它是用來控制子型態的方式,不過,它也意謂著一種(更強的)封裝意圖。

在過去,無論是哪種封裝意圖,在Java中都只能用類別來定義,其實Java 5的enum,就是試著將一種封裝意圖獨立出來的作法,而現在記錄類別、彌封類別,則是針對不同的封裝意圖,提供了相對應的特性支援;不同的封裝意圖,彼此之間可能重疊,也因此記錄類別、彌封類別等也可以結合使用,達到更細緻的封裝控制。

想瞭解封裝實際有哪些面向,建議你閱讀〈Data Classes and Sealed Types for Java〉,其中就談到了各種對封裝的見解,如果你有使用過Scala、Kotlin、C#的經驗,可以思考一下它們各自的使用情境。

為什麼我會將模式比對、記錄類別、彌封類別等,歸類於影響設計的語法呢?就這些特性未來版本的可能性來看,模式比對、記錄類別、彌封類別這三者,應該是要結合在一起看的,在未來各個特性完整之後,以我個人來看,Java試圖引入函數式設計中更進一步的觀念「代數資料型態」,讓未來的Java中,不會只有抽象資料型態的設計可能性。

試著認識代數資料型態

如果你有一陣子沒有關注Java了,面對Java 17,就結論而言,可以輕鬆地看待var、switch表示式、文字區塊,以及現階段的instanceof模式比對等新特性,畢竟它們的目的,就是簡化程式的撰寫。

至於記錄類別、彌封類別,就目前Java 17來說,我們可以從各不相同的封裝角度來看待它們,或者相對地,思考一下,過去使用POJO、JavaBean(甚至是Lombok)時,各自究竟是為了什麼封裝意圖。

就今日來看,函數式設計的基本概念,在開發者之間已經不陌生,而從Java 8開始到現在的Java 17,也早已經引入了許多函數式設計的元素;然而,長遠來看,Java正試著引入更細緻的函數式典範,也就是提供以代數資料型態為出發點的設計方式。

當然,就出生開始就是以抽象資料型態為出發點的Java而言,函數式是一種選擇,同樣地在未來,代數資料型態也是一種選擇,只不過保守的Java會納入這種選擇,表示它在其他語言中,已經有了一定程度的應用,不再是學術味濃厚的名詞。

未來的Java中,代數資料型態會是一種設計的方向,若你想為此做些準備,多認識一種設計方式,可以參先前專欄〈抽象資料型態與代數資料型態〉、〈重構與代數資料型態〉,或者從純函數式語言Haskell來認識,這會是一種最直接的管道。

專欄作者

熱門新聞

Advertisement