亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JDK19新特性使用實(shí)例詳解

 更新時間:2022年09月26日 15:19:32   作者:Throwable  
這篇文章主要為大家介紹了JDK19新特性使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前提

JDK192022-09-20發(fā)布GA版本,本文將會詳細(xì)介紹JDK19新特性的使用。

新特性列表

新特性列表如下:

  • JPE-405Record模式(預(yù)覽功能)
  • JPE-422JDK移植到Linux/RISC-V
  • JPE-424:外部函數(shù)和內(nèi)存API(預(yù)覽功能)
  • JPE-425:虛擬線程,也就是協(xié)程(預(yù)覽功能)
  • JPE-426:向量API(第四次孵化)
  • JPE-427switch匹配模式(第三次預(yù)覽)
  • JPE-428:結(jié)構(gòu)化并發(fā)(孵化功能)

新特性使用詳解

下面就每個新特性介紹其使用方式。

Record模式

使用Record模式增強(qiáng)Java編程語言以解構(gòu)Record值??梢郧短?code>Record模式和Type模式,以實(shí)現(xiàn)強(qiáng)大的、聲明性的和可組合的數(shù)據(jù)導(dǎo)航和處理形式。這個描述看起來有點(diǎn)抽象,下面舉幾個JEP-405的例子結(jié)合文字理解一下。以JDK16擴(kuò)展的instanceof關(guān)鍵字下使用Type模式來看:

// JDK16以前
private static void oldInstanceOf(Object x) {
    if (x instanceof String) {
        String s = (String) x;
        System.out.println(s);
    }
}
// JDK16或之后啟用instanceof下的Type模式
private static void newInstanceOfTypePattern(Object x) {
    if (x instanceof String s) {
        System.out.println(s);
    }
}

Type模式在JDK17JDK18擴(kuò)展到switch預(yù)覽功能中,應(yīng)用于其case標(biāo)簽:

// DEMO-1
private static void switchTypePattern(String s) {
    switch (s) {
        case null -> System.out.println("NULL");
        case "Foo", "Bar" -> System.out.println("Foo or Bar");
        default -> System.out.println("Default");
    }
}
// DEMO-2
interface Shape{}
class Rectangle implements Shape{}
class Triangle implements Shape{
    public int calculateArea(){
        return 200;
    }
}
private static void switchTypePatternForShape(Shape shape) {
    switch (shape) {
        case null:
            break;
        case Rectangle r:
            System.out.printf("Rectangle[%s]\n", r);
            break;
        case Triangle t:
            if (t.calculateArea() > 100) {
                System.out.printf("Large triangle[%s]\n", t);
            }
        default:
            System.out.println("Default shape");
    }
}
// DEMO-3 patterns in labels
private static void switchTypeForLabels(Object x) {
    String formatted = switch (x) {
        case Integer i -> String.format("int => %d", i);
        case Long l -> String.format("long => %d", l);
        case Double d -> String.format("double => %f", d);
        case String s -> String.format("string => %s", s);
        default -> x.toString();
    };
}

本次的Record模式預(yù)覽功能就是基于record關(guān)鍵字實(shí)現(xiàn)上面的Type類型或者switch模式。例如:

// DEMO-1
record Point(int x,int y){}
private static void printSum(Object o){
    if (o instanceof Point(int x,int y)){
        System.out.println(x + y);
    }
}

record類中如果存在泛型參數(shù)可以進(jìn)行類型轉(zhuǎn)換和推導(dǎo),例如:

// DEMO-2
record Holder<T>(T target){}
// 擦除后
private void convert(Holder<Object> holder){
    if (Objects.nonNull(holder) && holder instanceof Holder<Object>(String target)) {
        System.out.printf("string => %s\n", target);
    }
}
// 非擦除
private <T> void convert(Holder<T> holder){
    if (Objects.nonNull(holder) && holder instanceof Holder<T>(String target)) {
        System.out.printf("string => %s\n", target);
    }
}

然后看recordswitch結(jié)合使用:

// DEMO-3
sealed interface I permits C, D {}
final class C implements I {}
final class D implements I {}
Second<I,I> second;
private void recordSwitch() {
    second = new Second<>(new D(), new C());
    // second = new Second<>(new C(), new D());
    switch (second) {
        case Second<I, I>(C c,D d) -> System.out.printf("c => %s,d => %s", c, d);
        case Second<I, I>(D d,C c) -> System.out.printf("d => %s,c => %s", d, c);
        default -> System.out.println("default");
    }
}

這種模式比較復(fù)雜,因?yàn)樯婕暗?code>record類、switch模式、泛型參數(shù)并且參數(shù)類型是接口,case子句處理的時候必須覆蓋該泛型參數(shù)接口的所有子類型

不得不說,JDK引入的語法糖越來越復(fù)雜,功能看起來是強(qiáng)大的,但是編碼的可讀性在未適應(yīng)期有所下降

Linux/RISC-V移植

通過Linux/RISC-V移植,Java將獲得對硬件指令集的支持,該指令集已被廣泛的語言工具鏈支持。RISC-V是一種包含矢量指令的通用64ISA,目前該端口支持以下的HotSpot VM選項(xiàng):

  • 模板解釋器
  • 客戶端JIT編譯器
  • 服務(wù)端JIT編譯器
  • 包括ZGCShenandoah在內(nèi)的主流垃圾收集器

該移植基本已經(jīng)完成,JEP的重點(diǎn)是將該端口集成到JDK的主倉庫中。

外部函數(shù)和內(nèi)存API

外部函數(shù)和內(nèi)存API的主要功能是引入一組API,Java程序可以通過該組APIJava運(yùn)行時之外的代碼和數(shù)據(jù)進(jìn)行交互。有以下目標(biāo):

  • 易用性:通過卓越的純Java開發(fā)模型代替JNI
  • 高性能:提供能與當(dāng)前JNI或者Unsafe相當(dāng)甚至更優(yōu)的性能
  • 通用性:提供支持不同種類的外部內(nèi)存(如本地內(nèi)存、持久化內(nèi)存和托管堆內(nèi)存)的API,并隨著時間推移支持其他操作系統(tǒng)甚至其他語言編寫的外部函數(shù)
  • 安全性:允許程序?qū)ν獠績?nèi)存執(zhí)行不安全的操作,但默認(rèn)警告用戶此類操作

核心的API和功能如下:

  • 分配外部內(nèi)存:MemorySegment、MemoryAddressSegmentAllocator
  • 操作和訪問結(jié)構(gòu)化的外部內(nèi)存:MemoryLayoutVarHandle
  • 控制外部內(nèi)存:MemorySession
  • 調(diào)用外部函數(shù):Linker、FunctionDescriptorSymbolLookup

這些API統(tǒng)稱為FFM API,位于java.base模塊的java.lang.foreign包中。由于API比較多并且不算簡單,這里只舉一個簡單的例子:

public class AllocMemoryMain {
    public static void main(String[] args) {
        new AllocMemoryMain().allocMemory();
    }
    /**
     * 分配內(nèi)存
     * struct Point {
     * int x;
     * int y;
     * } pts[10];
     */
    public void allocMemory() {
        Random random = new Random();
        // 分配本地內(nèi)存
        MemorySegment segment = MemorySegment.allocateNative(2 * 4 * 10, MemorySession.openImplicit());
        // 創(chuàng)建順序內(nèi)存布局
        SequenceLayout ptsLayout = MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(
                ValueLayout.JAVA_INT.withName("x"),
                ValueLayout.JAVA_INT.withName("y")));
        // 對內(nèi)存設(shè)置值
        VarHandle xHandle = ptsLayout.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("x"));
        VarHandle yHandle = ptsLayout.varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("y"));
        for (int i = 0; i < ptsLayout.elementCount(); i++) {
            int x = i * random.nextInt(100);
            int y = i * random.nextInt(100);
            xHandle.set(segment,/* index */ (long) i,/* value to write */x); // x
            yHandle.set(segment,/* index */ (long) i,/* value to write */ y); // y
            System.out.printf("index => %d, x = %d, y = %d\n", i, x, y);
        }
        // 獲取內(nèi)存值
        int xValue = (int) xHandle.get(segment, 5);
        System.out.println("Point[5].x = " + xValue);
        int yValue = (int) yHandle.get(segment, 6);
        System.out.println("Point[6].y = " + yValue);
    }
}
// 某次執(zhí)行輸出結(jié)果
index => 0, x = 0, y = 0
index => 1, x = 79, y = 16
index => 2, x = 164, y = 134
index => 3, x = 150, y = 60
index => 4, x = 152, y = 232
index => 5, x = 495, y = 240
index => 6, x = 54, y = 162
index => 7, x = 406, y = 644
index => 8, x = 464, y = 144
index => 9, x = 153, y = 342
Point[5].x = 495
Point[6].y = 162

FFM API是一組極度強(qiáng)大的API,有了它可以靈活地安全地使用外部內(nèi)存和外部(跨語言)函數(shù)。

虛擬線程

虛擬線程,就是輕量級線程,也就是俗稱的協(xié)程,虛擬線程的資源分配和調(diào)度由VM實(shí)現(xiàn),與平臺線程(platform thread)有很大的不同。從目前的源代碼來看,虛擬線程的狀態(tài)管理、任務(wù)提交、休眠和喚醒等也是完全由VM實(shí)現(xiàn)。可以通過下面的方式創(chuàng)建虛擬線程:

// 方式一:直接啟動虛擬線程,因?yàn)槟J(rèn)參數(shù)原因這樣啟動的虛擬線程名稱為空字符串
Thread.startVirtualThread(() -> {
    Thread thread = Thread.currentThread();
    System.out.printf("線程名稱:%s,是否虛擬線程:%s\n", thread.getName(), thread.isVirtual());
});
// 方式二:Builder模式構(gòu)建
Thread vt = Thread.ofVirtual().allowSetThreadLocals(false)
        .name("VirtualWorker-", 0)
        .inheritInheritableThreadLocals(false)
        .unstarted(() -> {
            Thread thread = Thread.currentThread();
            System.out.printf("線程名稱:%s,是否虛擬線程:%s\n", thread.getName(), thread.isVirtual());
        });
vt.start();
// 方式三:Factory模式構(gòu)建
ThreadFactory factory = Thread.ofVirtual().allowSetThreadLocals(false)
        .name("VirtualFactoryWorker-", 0)
        .inheritInheritableThreadLocals(false)
        .factory();
Thread virtualWorker = factory.newThread(() -> {
    Thread thread = Thread.currentThread();
    System.out.printf("線程名稱:%s,是否虛擬線程:%s\n", thread.getName(), thread.isVirtual());
});
virtualWorker.start();
// 可以構(gòu)建"虛擬線程池"
ExecutorService executorService = Executors.newThreadPerTaskExecutor(factory);

由于虛擬線程的功能還處于預(yù)覽階段,創(chuàng)建協(xié)程的時候無法自定義執(zhí)行器(準(zhǔn)確來說是運(yùn)載線程),目前所有虛擬線程都是交由一個內(nèi)置的全局ForkJoinPool實(shí)例執(zhí)行,實(shí)現(xiàn)方式上和JDK8中新增的并行流比較接近。另外,目前來看虛擬線程和原來的JUC類庫是親和的,可以把虛擬線程替換原來JUC類庫中的Thread實(shí)例來嘗試使用(在生產(chǎn)應(yīng)用建議等該功能正式發(fā)布)

向量API

向量API目前是第四次孵化,功能是表達(dá)向量計算,在運(yùn)行時編譯為CPU 架構(gòu)上的最佳向量指令,從而實(shí)現(xiàn)優(yōu)于等效標(biāo)量計算的性能。目前相關(guān)API都在jdk.incubator.vector包下,使用的例子如下:

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
private static void vectorComputation(float[] a, float[] b, float[] c) {
    for (int i = 0; i < a.length; i += SPECIES.length()) {
        var m = SPECIES.indexInRange(i, a.length);
        var va = FloatVector.fromArray(SPECIES, a, i, m);
        var vb = FloatVector.fromArray(SPECIES, b, i, m);
        var vc = va.mul(va).add(vb.mul(vb)).neg();
        vc.intoArray(c, i, m);
    }
}
public static void main(String[] args) {
    float[] a = new float[]{1.0f, 3.0f, 2.0f};
    float[] b = {1.0f, -1.0f, 5.0f};
    float[] c = {1.0f, 6.0f, 1.0f};
    vectorComputation(a, b, c);
    System.out.println(Arrays.toString(c));
}

Vector有很多特化子類,可以通過不同的VectorSpecies進(jìn)行定義。

switch匹配模式

switch匹配模式第三次預(yù)覽,主要是對匹配模式進(jìn)行了擴(kuò)展。主要有幾點(diǎn)改進(jìn):

  • 增強(qiáng)類型校驗(yàn),case子句支持多種類型
record Point(int i, int j) {}
enum Color { RED, GREEN, BLUE; }
private void multiTypeCase(Object o) {
    switch (o) {
        case null -> System.out.println("null");
        case String s -> System.out.println("String");
        case Color c -> System.out.println("Color: " + c.toString());
        case Point p -> System.out.println("Record class: " + p.toString());
        case int[] ia -> System.out.println("Array of ints of length" + ia.length);
        default -> System.out.println("Something else");
    }
}
  • 增強(qiáng)表達(dá)式和語句的表現(xiàn)力和適用性,可以實(shí)現(xiàn)selector模式
private int selector(Object o) {
    return switch (o) {
        case String s -> s.length();
        case Integer i -> i;
        default -> 0;
    };
}
  • 擴(kuò)展模式變量聲明范圍
private void switchScope(Object o) {
    switch (o) {
        case Character c
                when c.charValue() == 7:
            System.out.println("Seven!");
            break;
        default:
            break;
    }
}
  • 優(yōu)化null處理
private void switchNull(Object o) {
    switch (o) {
        case null -> System.out.println("null!");
        case String s -> System.out.println("String");
        default -> System.out.println("Something else");
    }
}

結(jié)構(gòu)化并發(fā)

結(jié)構(gòu)化并發(fā)功能在孵化階段,該功能旨在通過結(jié)構(gòu)化并發(fā)庫來簡化多線程編程。結(jié)構(gòu)化并發(fā)提供的特性將在不同線程中運(yùn)行的多個任務(wù)視為一個工作單元,以簡化錯誤處理和取消,提高了可靠性和可觀測性。

record User(String name, Long id){}
record Order(String orderNo, Long id){}
record Response(User user, Order order){}
private User findUser(){
    throw new UnsupportedOperationException("findUser");
}
private Order fetchOrder(){
    throw new UnsupportedOperationException("fetchOrder");
}
private Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        Future&lt;User&gt; user = scope.fork(() -&gt; findUser());
        Future&lt;Order&gt; order = scope.fork(() -&gt; fetchOrder());
        scope.join();           // Join both forks
        scope.throwIfFailed();  // ... and propagate errors
        // Here, both forks have succeeded, so compose their results
        return new Response(user.resultNow(), order.resultNow());
    }
}

參考資料

JDK 19https://openjdk.org/projects/jdk/19,文中直接應(yīng)用部分文檔描述的翻譯

以上就是JDK19新特性使用實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于JDK19新特性的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java練習(xí)題之實(shí)現(xiàn)平方根(sqrt)函數(shù)

    Java練習(xí)題之實(shí)現(xiàn)平方根(sqrt)函數(shù)

    這篇文章主要介紹了Java練習(xí)題之實(shí)現(xiàn)平方根(sqrt)函數(shù)的相關(guān)資料,平方根是一個數(shù)學(xué)概念,表示一個數(shù)的正平方根,文中通過代碼和圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Swagger異常定位紀(jì)實(shí)Swagger設(shè)計問題分析

    Swagger異常定位紀(jì)實(shí)Swagger設(shè)計問題分析

    這篇文章主要為大家介紹了Swagger異常定位紀(jì)實(shí)Swagger設(shè)計的問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-02-02
  • Springboot自定義banner及驗(yàn)證過程

    Springboot自定義banner及驗(yàn)證過程

    這篇文章主要介紹了Springboot自定義banner及驗(yàn)證過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Java可變參數(shù)的應(yīng)用小結(jié)

    Java可變參數(shù)的應(yīng)用小結(jié)

    這篇文章主要介紹了Java可變參數(shù)的應(yīng)用小結(jié),實(shí)現(xiàn)同一個函數(shù)名,不同參數(shù)個數(shù),實(shí)現(xiàn)的方法相同,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-10-10
  • Java簡單工廠模式定義與用法實(shí)例分析

    Java簡單工廠模式定義與用法實(shí)例分析

    這篇文章主要介紹了Java簡單工廠模式定義與用法,結(jié)合實(shí)例形式分析了java簡單工廠模式的相關(guān)定義與使用技巧,并給出了原理類圖進(jìn)行總結(jié),需要的朋友可以參考下
    2019-07-07
  • elasticsearch聚合查詢實(shí)踐示例

    elasticsearch聚合查詢實(shí)踐示例

    這篇文章主要為大家介紹了elasticsearch聚合查詢實(shí)踐示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • JAVA設(shè)置手動提交事務(wù),回滾事務(wù),提交事務(wù)的操作

    JAVA設(shè)置手動提交事務(wù),回滾事務(wù),提交事務(wù)的操作

    這篇文章主要介紹了JAVA設(shè)置手動提交事務(wù),回滾事務(wù),提交事務(wù)的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • springboot 配置使用swagger2操作

    springboot 配置使用swagger2操作

    這篇文章主要介紹了springboot 配置使用swagger2操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java8中如何通過方法引用獲取屬性名詳解

    Java8中如何通過方法引用獲取屬性名詳解

    這篇文章主要給大家介紹了關(guān)于Java8中如何通過方法引用獲取屬性名的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java后臺處理Json格式數(shù)據(jù)的方法

    Java后臺處理Json格式數(shù)據(jù)的方法

    這篇文章主要介紹了Java后臺處理Json格式數(shù)據(jù)的方法的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06

最新評論