我有點想用JDK17了

👉 這是一個或許對你有用的社群
🐱 一對一交流/面試小冊/簡歷最佳化/求職解惑,歡迎加入芋道快速開發平臺知識星球。下面是星球提供的部分資料:
👉這是一個或許對你有用的開源專案
國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。
功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、CRM 等等功能:
  • Boot 倉庫:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 倉庫:https://gitee.com/zhijiantianya/yudao-cloud
  • 影片教程:https://doc.iocoder.cn
【國內首批】支援 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 雙版本 

JDK 版本升級的非常快,現在已經到 JDK20 了。JDK 版本雖多,但應用最廣泛的還得是 JDK8,正所謂“他發任他發,我用Java8”。
其實我也不太想升級 JDK 版本,感覺投入高,收益小,不過有一次我看到了一些使用 JDK17 新語法寫的程式碼,讓我改變了對升級 JDK 的看法,因為這些新語法我確實想用!
廢話不多說,上程式碼!

DK17語法新特性

文字塊

這個更新非常實用。在沒有這個特性之前,編寫長文字非常痛苦。雖然IDEA等整合開發工具可以自動處理,但最終效果仍然醜陋,充滿拼接符號。現在,透過字串塊,我們可以輕鬆編寫JSON、HTML、SQL等內容,效果更清爽。這個新特性值得五顆星評價,因為它讓我們只需關注字串本身,而無需關心拼接操作。
原來的寫法

/**

 * 使用JDK8返回HTML文字

 *

 * 

@return

 返回HTML文字

 */


publicstaticfinal String getHtmlJDK8()

{

return"<html>\n"

 +

" <body>\n"

 +

" <p>Hello, world</p>\n"

 +

" </body>\n"

 +

"</html>"

;

}

新的寫法

/**

 * 使用JDK17返回HTML文字

 * 

@return

 返回HTML文字

 */


publicstaticfinal String getHtmlJDK17()

{

return""

"

        <html>

            <body>

                <p>Hello, world</p>

            </body>

        </html>

        "

""

;

}

推薦指數:⭐️⭐️⭐️⭐️⭐️

NullPointerException增強

這一功能非常強大且實用,相信每位Java開發者都期待已久。空指標異常(NPE)一直是Java程式設計師的痛點,因為報錯資訊無法直觀地指出哪個物件為空,只丟擲一個NullPointerException和一堆堆疊資訊,定位問題耗時且麻煩。尤其在遇到喜歡級聯呼叫的程式碼時,逐行排查更是令人頭疼。如果在測試環境中,可能還需透過遠端除錯查明空物件,費時費力。為此,阿里的編碼規範甚至不允許級聯呼叫,但這並不能徹底解決問題。Java17終於在這方面取得了突破,提供了更詳細的空指標異常資訊,幫助開發者迅速定位問題源頭。
publicstaticvoidmain(String[] args)

{

try

 {

//簡單的空指標

        String str = 

null

;

        str.length();

    } 

catch

 (Exception e) {

        e.printStackTrace();

    }

try

 {

//複雜一點的空指標
var

 arr = List.of(

null

);

        String str = (String)arr.get(

0

);

        str.length();

    } 

catch

 (Exception e) {

        e.printStackTrace();

    }

}

執行結果
推薦指數:⭐️⭐️⭐️⭐️⭐️

Records

在Java中,POJO物件(如DO、PO、VO、DTO等)通常包含成員變數及相應的Getter和Setter方法。儘管可以透過工具或IDE生成這些程式碼,但修改和維護仍然麻煩。Lombok外掛為此出現,能夠在編譯期間自動生成Getter、Setter、hashcode、equals和建構函式等程式碼,使用起來方便,但對團隊有依賴要求。為此,Java引入了標準解決方案:Records。它透過簡潔的語法定義資料類,大大簡化了POJO類的編寫,如下所示。雖然hashcode和equals方法仍需手動編寫,但IDE能夠自動生成。這一特性有效解決了模板程式碼問題,提升了程式碼整潔度和可維護性。
package

 com.xttblog.jdk17;

/**

 * 3星

 *

 * 

@param

 stuId     學生ID

 * 

@param

 stuName   學生名稱

 * 

@param

 stuAge    學生年齡

 * 

@param

 stuGender 學生性別

 * 

@param

 stuEmail  學生郵箱

 */


public record StudentRecord

(Long stuId,

                            String stuName,

int

 stuAge,

                            String stuGender,

                            String stuEmail)

{

public

 StudentRecord {

        System.out.println(

"建構函式"

);

    }

publicstaticvoidmain(String[] args)

{

        StudentRecord record = 

new

 StudentRecord(

1L

"張三"

16

"男"

"[email protected]"

);

        System.out.println(record);

    }

}

推薦指數:⭐️⭐️⭐️⭐️

全新的switch表示式

有人可能問了,Java語言不早已支援switch了嘛,有什麼好提的?講真,這次的提升還真有必要好好地來聊一聊了。在Java12的時候就引入了switch表示式,注意這裡是表示式,而不是語句,原來的switch是語句。如果不清楚兩者的區別的話,最好先去了解一下。主要的差別就是就是表示式有返回值,而語句則沒有。再配合模式匹配,以及yield和“->”符號的加入,全新的switch用起來爽到飛起來。
package

 com.xttblog.jdk17;

publicclassSwitchDemo

{

/**

     * 在JDK8中獲取switch返回值方式

     *

     * 

@param

 week

     * 

@return

     */


publicintgetByJDK8(Week week)

{

int

 i = 

0

;

switch

 (week) {

case

 MONDAY, TUESDAY:

                i = 

1

;

break

;

case

 WEDNESDAY:

                i = 

3

;

break

;

case

 THURSDAY:

                i = 

4

;

break

;

case

 FRIDAY:

                i = 

5

;

break

;

case

 SATURDAY:

                i = 

6

;

break

;

case

 SUNDAY:

                i = 

7

;

break

;

default

:

                i = 

0

;

break

;

        }

return

 i;

    }

/**

     * 在JDK17中獲取switch返回值

     *

     * 

@param

 week

     * 

@return

     */


publicintgetByJDK17(Week week)

{

// 1, 現在的switch變成了表示式,可以返回值了,而且支援yield和->符號來返回值
// 2, 再也不用擔心漏寫了break,而導致出問題了
// 3, case後面支援寫多個條件
returnswitch

 (week) {

casenull

 -> -

1

;

case

 MONDAY -> 

1

;

case

 TUESDAY -> 

2

;

case

 WEDNESDAY -> 

3

;

case

 THURSDAY -> {yield 

4

;}

case

 FRIDAY -> 

5

;

case

 SATURDAY, SUNDAY -> 

6

;

default

 -> 

0

;

        };

    }

privateenum

 Week {

        MONDAY,

        TUESDAY,

        WEDNESDAY,

        THURSDAY,

        FRIDAY,

        SATURDAY,

        SUNDAY

    }

}

推薦指數:⭐️⭐️⭐️⭐️

私有介面方法

從Java8開始,允許在interface裡面新增預設方法,其實當時就有些小困惑,如果一個default方法體很大怎麼辦,拆到另外的類去寫嗎?實在有些不太合理,所以在Java17裡面,如果一個default方法體很大,那麼可以透過新增介面私有方法來進行一個合理的拆分了,為這個小改進點個贊。
publicinterfacePrivateInterfaceMethod

{

/**

     * 介面預設方法

     */


defaultvoiddefaultMethod()

{

        privateMethod();

    }

// 介面私有方法,在Java8裡面是不被允許的,不信你試試
privatevoidprivateMethod()

{

    }

}

推薦指數:⭐️⭐️⭐️

模式匹配

在JDK 17中,模式匹配主要用於instanceof表示式。模式匹配增強了instanceof的語法和功能,使型別檢查和型別轉換更加簡潔和高效。在傳統的Java版本中,我們通常使用instanceof結合型別轉換來判斷物件型別並進行處理,這往往會導致冗長的程式碼。
原來的寫法

/**

 * 舊式寫法

 *

 * 

@param

 value

 */


publicvoidmatchByJDK8(Object value)

{

if

 (value 

instanceof

 String) {

        String v = (String)value;

        System.out.println(

"遇到一個String型別"

 + v.toUpperCase());

    } 

elseif

 (value 

instanceof

 Integer) {

        Integer v = (Integer)value;

    System.out.println(

"遇到一個整型型別"

 + v.longValue());

    }

}

新的寫法

/**

 * 轉換並申請了一個新的變數,極大地方便了程式碼的編寫

 *

 * 

@param

 value

 */


publicvoidmatchByJDK17(Object value)

{

if

 (value 

instanceof

 String v) {

        System.out.println(

"遇到一個String型別"

 + v.toUpperCase());

    } 

elseif

 (value 

instanceof

 Integer v) {

        System.out.println(

"遇到一個整型型別"

 + v.longValue());

    }

}

推薦指數:⭐️⭐️⭐️⭐️

集合類的工廠方法

在Java8的年代,即便建立一個很小的集合,或者固定元素的集合都是比較麻煩的,為了簡潔一些,有時我甚至會引入一些依賴。
原來的寫法

Set<String> set = 

new

 HashSet<>();

set.add(

"a"

);

set.add(

"b"

);

set.add(

"c"

新的寫法

Set<String> set = Set.of(

"a"

"b"

"c"

);

推薦指數:⭐️⭐️⭐️⭐️⭐️
基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
  • 專案地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 影片教程:https://doc.iocoder.cn/video/

其他的新特性

新的String方法

  • repeat:重複生成字串
  • isBlank:不用在引入第三方庫就可以實現字串判空了
  • strip:去除字串兩邊的空格,支援全形和半形,之前的trim只支援半形
  • lines:能根據一段字串中的終止符提取出行為單位的流
  • indent:給字串做縮排,接受一個int型的輸入
  • transform:接受一個轉換函式,實現字串的轉換

Stream API的增強

增加takeWhile, dropWhile, ofNullable, iterate以及toList的API,越來越像一些函式式語言了。用法舉例如下。
// takeWhile 順序返回符合條件的值,直到條件不符合時即終止繼續判斷,
// 此外toList方法的加入,也大大減少了節省了程式碼量,免去了呼叫collect(Collectors::toList)方法了

List<Integer> list = Stream.of(

2

,

2

,

3

,

4

,

5

,

6

,

7

,

8

,

9

,

10

)

        .takeWhile(i->(i%

2

==

0

)).toList(); 

// 返回2, 2

// dropWhile 順序去掉符合條件的值,直到條件不符合時即終止繼續判斷

List<Integer> list1 = Stream.of(

2

,

2

,

3

,

4

,

5

,

6

,

7

,

8

,

9

,

10

)

        .dropWhile(i->(i%

2

==

0

)).toList(); 

//返回3, 4, 5, 6, 7, 8, 9, 10

// ofNullable,支援傳入空流,若沒有這個且傳入一個空流,那麼將會拋NPE
var

 nullStreamCount = Stream.ofNullable(

null

).count(); 

//返回0

// 以下兩行都將輸出0到9

Stream.iterate(

0

, n -> n < 

10

, n -> n + 

1

).forEach(x -> System.out.println(x));

Stream.iterate(

0

, n -> n + 

1

).limit(

10

).forEach(x -> System.out.println(x));

全新的HttpClient

這個API首次出現在9之中,不過當時並非是一個穩定版本,在Java11中正式得到釋出,所以在Java17裡面可以放心地進行使用。原來的JDK自帶的Http客戶端真的非常難用,這也就給了很多像okhttp、restTemplate、Apache的HttpClient和feign這樣的第三方庫極大的發揮空間,幾乎就沒有人願意去用原生的Http客戶端的。但現在不一樣了,感覺像是新時代的API了。FluentAPI風格,處處充滿了現代風格,用起來也非常地方便,再也不用去依賴第三方的包了,就兩個字,清爽。
// 同步請求

HttpClient client = HttpClient.newBuilder()

        .version(Version.HTTP_1_1)

        .followRedirects(Redirect.NORMAL)

        .connectTimeout(Duration.ofSeconds(

20

))

        .proxy(ProxySelector.of(

new

 InetSocketAddress(

"proxy.example.com"

80

)))

        .authenticator(Authenticator.getDefault())

        .build();

   HttpResponse<String> response = client.send(request, BodyHandlers.ofString());

   System.out.println(response.statusCode());

   System.out.println(response.body()); 

// 非同步請求

HttpRequest request = HttpRequest.newBuilder()

        .uri(URI.create(

"https://foo.com/"

))

        .timeout(Duration.ofMinutes(

2

))

        .header(

"Content-Type"

"application/json"

)

        .POST(BodyPublishers.ofFile(Paths.get(

"file.json"

)))

        .build();

   client.sendAsync(request, BodyHandlers.ofString())

        .thenApply(HttpResponse::body)

        .thenAccept(System.out::println);

jshell

在新的JDK版本中,支援直接在命令列下執行java程式,類似於python的互動式REPL。簡而言之,使用 JShell,你可以輸入程式碼片段並馬上看到執行結果,然後就可以根據需要作出調整,這樣在驗證一些簡單的程式碼的時候,就可以透過jshell得到快速地驗證,非常方便。

java命令直接執行java檔案

在現在可以直接透過執行“java xxx.java”,即可執行該java檔案,無須先執行javac,然後再執行java,是不是又簡單了一步。

ZGC

在ParallelOldGC、CMS和G1之後,JDK 11引入了全新的ZGC(Z Garbage Collector)。這個名字本身就顯得很牛。官方宣稱ZGC的垃圾回收停頓時間不超過10ms,能支援高達16TB的堆空間,並且停頓時間不會隨著堆的增大而增加。那麼,ZGC到底解決了什麼問題?Oracle官方介紹它是一個可伸縮的低延遲垃圾回收器,旨在降低停頓時間,儘管這可能會導致吞吐量的降低。不過,透過橫向擴充套件伺服器可以解決吞吐量問題。官方已建議ZGC可用於生產環境,這無疑將成為未來的主流垃圾回收器。要了解更多,請參閱官方文件https://docs.oracle.com/en/java/javase/17/gctuning/z-garbage-collector.html#GUID-9957D441-A99A-4CF5-9522-393E6DE7D898

小結一下

作為程式設計師,持續學習和充電非常重要。隨著Java8即將停止免費官方支援,越來越多的專案將轉向Java17,包括大名鼎鼎的Spring Boot 3.0,它在2022年1月20日釋出的第一個里程碑版本(M1)正是基於Java17構建的。該專案依賴的所有元件也將快速升級,未來如果想利用某些新特性,在Java8下將無法透過編譯,到這時候再換就真的晚了… …

歡迎加入我的知識星球,全面提升技術能力。
👉 加入方式,長按”或“掃描”下方二維碼噢
星球的內容包括:專案實戰、面試招聘、原始碼解析、學習路線。
文章有幫助的話,在看,轉發吧。
謝謝支援喲 (*^__^*)

相關文章