Java?17新特性詳細(xì)講解與代碼實例
前言
Java 17是Java SE 17的開源參考實現(xiàn),于2021年9月14日正式發(fā)布,是Java 11以來的又一個長期支持(LTS)版本。Java 17中有一些新的特性和改進,本文將對它們進行簡要的介紹和示例。
密封類
密封類和接口限制了哪些其他類或接口可以擴展或?qū)崿F(xiàn)它們,增強了封裝性和可維護性。密封類由JEP 360并在JDK 15中作為預(yù)覽功能交付。它們再次被提出,并進行了改進,由JEP 397并在JDK 16中作為預(yù)覽功能提供。現(xiàn)在,在JDK 17中,密封類正在最終確定,與JDK 16沒有任何更改。
要定義一個密封類或接口,需要使用sealed
修飾符,并且在聲明中指定允許擴展或?qū)崿F(xiàn)它的其他類或接口。這些類或接口被稱為子類或子接口。子類或子接口可以使用final
修飾符來表示它們不能被進一步擴展或?qū)崿F(xiàn),或者使用sealed
修飾符來表示它們也是密封的,并且需要指定它們的子類或子接口,或者使用non-sealed
修飾符來表示它們不是密封的,并且可以被任意的類或接口擴展或?qū)崿F(xiàn)。
例如,我們可以定義一個密封的形狀接口Shape,并且指定它只能被Circle、Rectangle和Triangle這三個類實現(xiàn):
public sealed interface Shape permits Circle, Rectangle, Triangle { double area(); }
然后,我們可以定義這三個類,并且分別使用final
、sealed
和non-sealed
修飾符:
public final class Circle implements Shape { private final double radius; public Circle(double radius) { this.radius = radius; } public double area() { return Math.PI * radius * radius; } } public sealed class Rectangle implements Shape permits Square { private final double length; private final double width; public Rectangle(double length, double width) { this.length = length; this.width = width; } public double area() { return length * width; } } public non-sealed class Triangle implements Shape { private final double base; private final double height; public Triangle(double base, double height) { this.base = base; this.height = height; } public double area() { return base * height / 2; } }
注意,Square是Rectangle的子類,并且也是密封的:
public final class Square extends Rectangle { public Square(double side) { super(side, side); } }
這樣,我們就可以保證Shape接口只能被這四個類實現(xiàn),而不會有其他的可能性。我們也可以使用模式匹配來對不同的形狀進行操作,例如:
public static void printArea(Shape shape) { if (shape instanceof Circle c) { System.out.println("The area of the circle is " + c.area()); } else if (shape instanceof Rectangle r) { System.out.println("The area of the rectangle is " + r.area()); } else if (shape instanceof Triangle t) { System.out.println("The area of the triangle is " + t.area()); } }
switch表達(dá)式
switch表達(dá)式允許switch有返回值,并且可以直接作為結(jié)果賦值給一個變量,簡化了多分支的邏輯。switch表達(dá)式由JEP 325并在JDK 12中作為預(yù)覽功能交付。它們再次被提出,并進行了改進,由JEP 354并在JDK 13中作為預(yù)覽功能提供。它們再次被提出,并進行了改進,由JEP 361并在JDK 14中作為預(yù)覽功能提供?,F(xiàn)在,在JDK 17中,switch表達(dá)式正在最終確定,與JDK 14沒有任何更改。
要定義一個switch表達(dá)式,需要使用->
符號來表示每個分支的結(jié)果,并且在表達(dá)式的末尾加上一個分號。例如,我們可以定義一個根據(jù)月份返回季節(jié)的switch表達(dá)式:
public static String getSeason(int month) { return switch (month) { case 12, 1, 2 -> "Winter"; case 3, 4, 5 -> "Spring"; case 6, 7, 8 -> "Summer"; case 9, 10, 11 -> "Autumn"; default -> "Unknown"; }; }
注意,我們可以使用逗號來分隔多個匹配值,也可以使用default來表示其他情況。我們也可以使用yield關(guān)鍵字來返回一個值,這在需要在返回之前進行一些操作的情況下很有用,例如:
public static String getSeason(int month) { return switch (month) { case 12, 1, 2 -> { System.out.println("It's cold!"); yield "Winter"; } case 3, 4, 5 -> { System.out.println("It's warm!"); yield "Spring"; } case 6, 7, 8 -> { System.out.println("It's hot!"); yield "Summer"; } case 9, 10, 11 -> { System.out.println("It's cool!"); yield "Autumn"; } default -> { System.out.println("It's unknown!"); yield "Unknown"; } }; }
文本塊
文本塊允許使用三個雙引號來定義一個多行的字符串,避免了轉(zhuǎn)義和拼接的麻煩。文本塊由JEP
355并在JDK 13中作為預(yù)覽功能交付。它們再次被提出,并進行了改進,由JEP 368并在JDK 14中作為預(yù)覽功能提供。它們再次被提出,并進行了改進,由JEP 378并在JDK 15中作為預(yù)覽功能提供?,F(xiàn)在,在JDK 17中,文本塊正在最終確定,與JDK 15沒有任何更改。
要定義一個文本塊,需要使用三個雙引號"""
來開始和結(jié)束,并且結(jié)束的三個雙引號不能和開始的在同一行。例如,我們可以定義一個包含JSON數(shù)據(jù)的文本塊:
public static String getJson() { return """ { "name": "Java", "version": 17, "features": [ "sealed classes", "switch expressions", "text blocks" ] } """; }
注意,文本塊中的換行符會被保留,而不需要使用\n
來表示。我們也可以使用\
來表示忽略換行符,或者使用\s
來表示一個空格。例如:
public static String getGreeting() { return """ Hello,\ World! """; } public static String getPoem() { return """ Twinkle, twinkle, little star,\s How I wonder what you are.\s Up above the world so high,\s Like a diamond in the sky. """; }
模式匹配
模式匹配允許在instanceof和switch中使用模式來測試表達(dá)式的類型和結(jié)構(gòu),提高了代碼的可讀性和靈活性。模式匹配由JEP 305并在JDK 14中作為預(yù)覽功能交付。它們再次被提出,并進行了改進,由JEP 375并在JDK 15中作為預(yù)覽功能提供。它們再次被提出,并進行了改進,由JEP 394并在JDK 16中作為預(yù)覽功能提供?,F(xiàn)在,在JDK 17中,模式匹配正在最終確定,與JDK 16沒有任何更改。
要使用模式匹配,需要使用instanceof
或switch
關(guān)鍵字,并且在測試的類型后面加上一個變量名,用于綁定匹配的值。例如,我們可以使用模式匹配來判斷一個對象是否是字符串,并且獲取它的長度:
public static void printLength(Object obj) { if (obj instanceof String s) { System.out.println("The length of the string is " + s.length()); } else { System.out.println("The object is not a string"); } }
注意,我們不需要再進行強制類型轉(zhuǎn)換,因為變量s
已經(jīng)被綁定為字符串類型。我們也可以使用模式匹配來判斷一個對象是否是密封類的子類,并且獲取它的屬性:
public static void printShape(Shape shape) { switch (shape) { case Circle c -> System.out.println("The radius of the circle is " + c.radius()); case Rectangle r -> System.out.println("The area of the rectangle is " + r.area()); case Triangle t -> System.out.println("The base of the triangle is " + t.base()); default -> System.out.println("Unknown shape"); } }
注意,我們不需要再進行類型檢查或者類型轉(zhuǎn)換,因為變量c
、r
和t
已經(jīng)被綁定為相應(yīng)的類型。
增強型偽隨機數(shù)生成器
增強型偽隨機數(shù)生成器為PRNG提供了新的接口類型和實現(xiàn),包括可跳轉(zhuǎn)的PRNG和一類額外的可拆分PRNG算法(LXM)。增強型偽隨機數(shù)生成器由JEP 356并在JDK 17中作為正式功能提供。
要使用增強型偽隨機數(shù)生成器,需要使用java.util.random
包中的新的接口和類。例如,我們可以使用RandomGenerator
接口來獲取一個PRNG的實例,并且使用它來生成各種類型的隨機數(shù):
public static void generateRandomNumbers() { RandomGenerator random = RandomGenerator.getDefault(); System.out.println("A random boolean: " + random.nextBoolean()); System.out.println("A random int: " + random.nextInt()); System.out.println("A random long: " + random.nextLong()); System.out.println("A random float: " + random.nextFloat()); System.out.println("A random double: " + random.nextDouble()); }
注意,RandomGenerator
接口提供了很多方便的方法來生成不同范圍和分布的隨機數(shù),例如nextInt(int bound)
、nextLong(long bound)
、nextGaussian()
等。我們也可以使用RandomGeneratorFactory
類來獲取不同的PRNG算法的實例,例如:
public static void useDifferentAlgorithms() { RandomGenerator random1 = RandomGeneratorFactory.of("L32X64MixRandom"); RandomGenerator random2 = RandomGeneratorFactory.of("L64X128MixRandom"); RandomGenerator random3 = RandomGeneratorFactory.of("L128X256MixRandom"); System.out.println("Using L32X64MixRandom: " + random1.nextInt()); System.out.println("Using L64X128MixRandom: " + random2.nextInt()); System.out.println("Using L128X256MixRandom: " + random3.nextInt()); }
注意,RandomGeneratorFactory
類提供了很多方法來獲取或者查詢不同的PRNG算法,例如of(String name)
、all()
、preferred()
等。我們也可以使用JumpableRandomGenerator
接口或者SplittableRandomGenerator
接口來獲取一個可跳轉(zhuǎn)或者可拆分的PRNG實例,并且使用它們來生成不同的子生成器,例如:
public static void useJumpableOrSplittableGenerators() { JumpableRandomGenerator jumpable = RandomGeneratorFactory.jumpable(); SplittableRandomGenerator splittable = RandomGeneratorFactory.splittable(); System.out.println("Using the original jumpable generator: " + jumpable.nextInt()); System.out.println("Using the original splittable generator: " + splittable.nextInt()); JumpableRandomGenerator jumped = jumpable.jump(); SplittableRandomGenerator splitted = splittable.split(); System.out.println("Using the jumped generator: " + jumped.nextInt()); System.out.println("Using the splitted generator: " + splitted.nextInt()); }
注意,JumpableRandomGenerator
接口和SplittableRandomGenerator
接口都繼承自RandomGenerator
接口,并且提供了額外的方法來生成子生成器,例如jump()
、split()
等。這些子生成器可以用于并行計算或者其他場景。
新的macOS渲染管道
新的macOS渲染管道使用Apple Metal加速渲染API來替代被Apple棄用的OpenGL API。新的macOS渲染管道由JEP 382并在JDK 17中作為正式功能提供。
要使用新的macOS渲染管道,需要在運行Java程序時設(shè)置系統(tǒng)屬性:
-Dsun.java2d.metal=true
這樣,Java 2D API和Swing API用于渲染的Java 2D API就可以使用Metal API來加速渲染。這對于Java程序是透明的,因為這是內(nèi)部實現(xiàn)的區(qū)別,對Java API沒有影響。Metal管道需要macOS 10.14.x或更高版本。在早期版本上設(shè)置它的嘗試將被忽略。
總結(jié)
到此這篇關(guān)于Java 17新特性的文章就介紹到這了,更多相關(guān)Java17新特性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)的具有GUI的校園導(dǎo)航系統(tǒng)的完整代碼
這篇文章主要介紹了Java實現(xiàn)的具有GUI的校園導(dǎo)航系統(tǒng)的完整代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決
這篇文章主要介紹了OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06springcloud之Feign、ribbon如何設(shè)置超時時間和重試機制
這篇文章主要介紹了springcloud之Feign、ribbon如何設(shè)置超時時間和重試機制,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08Java畢業(yè)設(shè)計實戰(zhàn)之二手書商城系統(tǒng)的實現(xiàn)
這是一個使用了java+JSP+Springboot+maven+mysql+ThymeLeaf+FTP開發(fā)的二手書商城系統(tǒng),是一個畢業(yè)設(shè)計的實戰(zhàn)練習(xí),具有在線書城該有的所有功能,感興趣的朋友快來看看吧2022-01-01使用try-with-resource的輸入輸出流自動關(guān)閉
這篇文章主要介紹了使用try-with-resource的輸入輸出流自動關(guān)閉方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07SpringBoot實現(xiàn)websocket服務(wù)端及客戶端的詳細(xì)過程
文章介紹了WebSocket通信過程、服務(wù)端和客戶端的實現(xiàn),以及可能遇到的問題及解決方案,感興趣的朋友一起看看吧2024-12-12Java?方法(方法的定義,可變參數(shù),參數(shù)的傳遞問題,方法重載,方法簽名)
這篇文章主要介紹了Java?方法(方法的定義,可變參數(shù),參數(shù)的傳遞問題,方法重載,方法簽名),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下2022-09-09