Java?17新特性詳細(xì)講解與代碼實例
前言
Java 17是Java SE 17的開源參考實現(xiàn),于2021年9月14日正式發(fā)布,是Java 11以來的又一個長期支持(LTS)版本。Java 17中有一些新的特性和改進(jìn),本文將對它們進(jìn)行簡要的介紹和示例。
密封類
密封類和接口限制了哪些其他類或接口可以擴(kuò)展或?qū)崿F(xiàn)它們,增強(qiáng)了封裝性和可維護(hù)性。密封類由JEP 360并在JDK 15中作為預(yù)覽功能交付。它們再次被提出,并進(jìn)行了改進(jìn),由JEP 397并在JDK 16中作為預(yù)覽功能提供?,F(xiàn)在,在JDK 17中,密封類正在最終確定,與JDK 16沒有任何更改。
要定義一個密封類或接口,需要使用sealed修飾符,并且在聲明中指定允許擴(kuò)展或?qū)崿F(xiàn)它的其他類或接口。這些類或接口被稱為子類或子接口。子類或子接口可以使用final修飾符來表示它們不能被進(jìn)一步擴(kuò)展或?qū)崿F(xiàn),或者使用sealed修飾符來表示它們也是密封的,并且需要指定它們的子類或子接口,或者使用non-sealed修飾符來表示它們不是密封的,并且可以被任意的類或接口擴(kuò)展或?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),而不會有其他的可能性。我們也可以使用模式匹配來對不同的形狀進(jì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ù)覽功能交付。它們再次被提出,并進(jìn)行了改進(jìn),由JEP 354并在JDK 13中作為預(yù)覽功能提供。它們再次被提出,并進(jìn)行了改進(jìn),由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)鍵字來返回一個值,這在需要在返回之前進(jì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ù)覽功能交付。它們再次被提出,并進(jìn)行了改進(jìn),由JEP 368并在JDK 14中作為預(yù)覽功能提供。它們再次被提出,并進(jìn)行了改進(jìn),由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ù)覽功能交付。它們再次被提出,并進(jìn)行了改進(jìn),由JEP 375并在JDK 15中作為預(yù)覽功能提供。它們再次被提出,并進(jìn)行了改進(jìn),由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");
}
}注意,我們不需要再進(jìn)行強(qiáng)制類型轉(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");
}
}注意,我們不需要再進(jìn)行類型檢查或者類型轉(zhuǎn)換,因為變量c、r和t已經(jīng)被綁定為相應(yīng)的類型。
增強(qiáng)型偽隨機(jī)數(shù)生成器
增強(qiáng)型偽隨機(jī)數(shù)生成器為PRNG提供了新的接口類型和實現(xiàn),包括可跳轉(zhuǎn)的PRNG和一類額外的可拆分PRNG算法(LXM)。增強(qiáng)型偽隨機(jī)數(shù)生成器由JEP 356并在JDK 17中作為正式功能提供。
要使用增強(qiáng)型偽隨機(jī)數(shù)生成器,需要使用java.util.random包中的新的接口和類。例如,我們可以使用RandomGenerator接口來獲取一個PRNG的實例,并且使用它來生成各種類型的隨機(jī)數(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接口提供了很多方便的方法來生成不同范圍和分布的隨機(jī)數(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)文章
Flyway詳解及Springboot集成Flyway的詳細(xì)教程
Flayway是一款數(shù)據(jù)庫版本控制管理工具,,支持?jǐn)?shù)據(jù)庫版本自動升級,Migrations可以寫成sql腳本,也可以寫在java代碼里。這篇文章主要介紹了Flyway詳解及Springboot集成Flyway的詳細(xì)教程的相關(guān)資料,需要的朋友可以參考下2020-07-07
詳解Spring Boot 目錄文件結(jié)構(gòu)
這篇文章主要介紹了Spring Boot 目錄文件結(jié)構(gòu)的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07
SpringBoot整合Minio實現(xiàn)上傳文件的完整步驟記錄
MinIO是一個基于Apache License v2.0開源協(xié)議的對象存儲服務(wù),它兼容亞馬遜S3云存儲服務(wù)接口,非常適合于存儲大容量非結(jié)構(gòu)化的數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合Minio實現(xiàn)上傳文件的完整步驟,需要的朋友可以參考下2022-05-05
Springboot vue導(dǎo)出功能實現(xiàn)代碼
這篇文章主要介紹了Springboot vue導(dǎo)出功能實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04
IDEA的部署設(shè)置改為war exploded運行項目出錯問題
在使用IDEA配置warexploded部署時,可能會遇到路徑問題或404錯誤,解決方法是進(jìn)入Deployment設(shè)置,刪除Application content中的/marry_war_exploded,使其為空,然后重新運行項目即可,這是一種有效的解決策略,希望能幫助到遇到同樣問題的開發(fā)者2024-10-10

