欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?17新特性詳細(xì)講解與代碼實(shí)例

 更新時(shí)間:2023年09月25日 15:32:22   作者:夏客柯  
這篇文章主要給大家介紹了關(guān)于Java?17新特性詳細(xì)講解與代碼實(shí)例的相關(guān)資料,Java 17是2021年9月發(fā)布的最新版本,其中包含了很多新特性和改進(jìn),這些新特性和改進(jìn)將進(jìn)一步提高 Java 語(yǔ)言的性能和可用性,需要的朋友可以參考下

前言

Java 17是Java SE 17的開(kāi)源參考實(shí)現(xiàn),于2021年9月14日正式發(fā)布,是Java 11以來(lái)的又一個(gè)長(zhǎng)期支持(LTS)版本。Java 17中有一些新的特性和改進(jìn),本文將對(duì)它們進(jìn)行簡(jiǎn)要的介紹和示例。

密封類

密封類和接口限制了哪些其他類或接口可以擴(kuò)展或?qū)崿F(xiàn)它們,增強(qiáng)了封裝性和可維護(hù)性。密封類由JEP 360并在JDK 15中作為預(yù)覽功能交付。它們?cè)俅伪惶岢?,并進(jìn)行了改進(jìn),由JEP 397并在JDK 16中作為預(yù)覽功能提供?,F(xiàn)在,在JDK 17中,密封類正在最終確定,與JDK 16沒(méi)有任何更改。

要定義一個(gè)密封類或接口,需要使用sealed修飾符,并且在聲明中指定允許擴(kuò)展或?qū)崿F(xiàn)它的其他類或接口。這些類或接口被稱為子類或子接口。子類或子接口可以使用final修飾符來(lái)表示它們不能被進(jìn)一步擴(kuò)展或?qū)崿F(xiàn),或者使用sealed修飾符來(lái)表示它們也是密封的,并且需要指定它們的子類或子接口,或者使用non-sealed修飾符來(lái)表示它們不是密封的,并且可以被任意的類或接口擴(kuò)展或?qū)崿F(xiàn)。

例如,我們可以定義一個(gè)密封的形狀接口Shape,并且指定它只能被Circle、Rectangle和Triangle這三個(gè)類實(shí)現(xiàn):

public sealed interface Shape permits Circle, Rectangle, Triangle {
    double area();
}

然后,我們可以定義這三個(gè)類,并且分別使用final、sealednon-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接口只能被這四個(gè)類實(shí)現(xiàn),而不會(huì)有其他的可能性。我們也可以使用模式匹配來(lái)對(duì)不同的形狀進(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é)果賦值給一個(gè)變量,簡(jiǎn)化了多分支的邏輯。switch表達(dá)式由JEP 325并在JDK 12中作為預(yù)覽功能交付。它們?cè)俅伪惶岢觯⑦M(jìn)行了改進(jìn),由JEP 354并在JDK 13中作為預(yù)覽功能提供。它們?cè)俅伪惶岢?,并進(jìn)行了改進(jìn),由JEP 361并在JDK 14中作為預(yù)覽功能提供?,F(xiàn)在,在JDK 17中,switch表達(dá)式正在最終確定,與JDK 14沒(méi)有任何更改。

要定義一個(gè)switch表達(dá)式,需要使用->符號(hào)來(lái)表示每個(gè)分支的結(jié)果,并且在表達(dá)式的末尾加上一個(gè)分號(hào)。例如,我們可以定義一個(gè)根據(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";
    };
}

注意,我們可以使用逗號(hào)來(lái)分隔多個(gè)匹配值,也可以使用default來(lái)表示其他情況。我們也可以使用yield關(guān)鍵字來(lái)返回一個(gè)值,這在需要在返回之前進(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";
        }
    };
}

文本塊

文本塊允許使用三個(gè)雙引號(hào)來(lái)定義一個(gè)多行的字符串,避免了轉(zhuǎn)義和拼接的麻煩。文本塊由JEP

355并在JDK 13中作為預(yù)覽功能交付。它們?cè)俅伪惶岢?,并進(jìn)行了改進(jìn),由JEP 368并在JDK 14中作為預(yù)覽功能提供。它們?cè)俅伪惶岢?,并進(jìn)行了改進(jìn),由JEP 378并在JDK 15中作為預(yù)覽功能提供。現(xiàn)在,在JDK 17中,文本塊正在最終確定,與JDK 15沒(méi)有任何更改。

要定義一個(gè)文本塊,需要使用三個(gè)雙引號(hào)"""來(lái)開(kāi)始和結(jié)束,并且結(jié)束的三個(gè)雙引號(hào)不能和開(kāi)始的在同一行。例如,我們可以定義一個(gè)包含JSON數(shù)據(jù)的文本塊:

public static String getJson() {
    return """
    {
        "name": "Java",
        "version": 17,
        "features": [
            "sealed classes",
            "switch expressions",
            "text blocks"
        ]
    }
    """;
}

注意,文本塊中的換行符會(huì)被保留,而不需要使用\n來(lái)表示。我們也可以使用\來(lái)表示忽略換行符,或者使用\s來(lái)表示一個(gè)空格。例如:

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中使用模式來(lái)測(cè)試表達(dá)式的類型和結(jié)構(gòu),提高了代碼的可讀性和靈活性。模式匹配由JEP 305并在JDK 14中作為預(yù)覽功能交付。它們?cè)俅伪惶岢?,并進(jìn)行了改進(jìn),由JEP 375并在JDK 15中作為預(yù)覽功能提供。它們?cè)俅伪惶岢?,并進(jìn)行了改進(jìn),由JEP 394并在JDK 16中作為預(yù)覽功能提供?,F(xiàn)在,在JDK 17中,模式匹配正在最終確定,與JDK 16沒(méi)有任何更改。

要使用模式匹配,需要使用instanceofswitch關(guān)鍵字,并且在測(cè)試的類型后面加上一個(gè)變量名,用于綁定匹配的值。例如,我們可以使用模式匹配來(lái)判斷一個(gè)對(duì)象是否是字符串,并且獲取它的長(zhǎng)度:

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)換,因?yàn)樽兞?code>s已經(jīng)被綁定為字符串類型。我們也可以使用模式匹配來(lái)判斷一個(gè)對(duì)象是否是密封類的子類,并且獲取它的屬性:

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)換,因?yàn)樽兞?code>c、rt已經(jīng)被綁定為相應(yīng)的類型。

增強(qiáng)型偽隨機(jī)數(shù)生成器

增強(qiáng)型偽隨機(jī)數(shù)生成器為PRNG提供了新的接口類型和實(shí)現(xiàn),包括可跳轉(zhuǎn)的PRNG和一類額外的可拆分PRNG算法(LXM)。增強(qiáng)型偽隨機(jī)數(shù)生成器由JEP 356并在JDK 17中作為正式功能提供。

要使用增強(qiáng)型偽隨機(jī)數(shù)生成器,需要使用java.util.random包中的新的接口和類。例如,我們可以使用RandomGenerator接口來(lái)獲取一個(gè)PRNG的實(shí)例,并且使用它來(lái)生成各種類型的隨機(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接口提供了很多方便的方法來(lái)生成不同范圍和分布的隨機(jī)數(shù),例如nextInt(int bound)nextLong(long bound)、nextGaussian()等。我們也可以使用RandomGeneratorFactory類來(lái)獲取不同的PRNG算法的實(shí)例,例如:

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類提供了很多方法來(lái)獲取或者查詢不同的PRNG算法,例如of(String name)、all()preferred()等。我們也可以使用JumpableRandomGenerator接口或者SplittableRandomGenerator接口來(lái)獲取一個(gè)可跳轉(zhuǎn)或者可拆分的PRNG實(shí)例,并且使用它們來(lái)生成不同的子生成器,例如:

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接口,并且提供了額外的方法來(lái)生成子生成器,例如jump()、split()等。這些子生成器可以用于并行計(jì)算或者其他場(chǎng)景。

新的macOS渲染管道

新的macOS渲染管道使用Apple Metal加速渲染API來(lái)替代被Apple棄用的OpenGL API。新的macOS渲染管道由JEP 382并在JDK 17中作為正式功能提供。

要使用新的macOS渲染管道,需要在運(yùn)行Java程序時(shí)設(shè)置系統(tǒng)屬性:

-Dsun.java2d.metal=true

這樣,Java 2D API和Swing API用于渲染的Java 2D API就可以使用Metal API來(lái)加速渲染。這對(duì)于Java程序是透明的,因?yàn)檫@是內(nèi)部實(shí)現(xiàn)的區(qū)別,對(duì)Java API沒(méi)有影響。Metal管道需要macOS 10.14.x或更高版本。在早期版本上設(shè)置它的嘗試將被忽略。

總結(jié)

到此這篇關(guān)于Java 17新特性的文章就介紹到這了,更多相關(guān)Java17新特性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論