Java21来了,赶紧用起来(附代码使用示例)

这篇具有很好参考价值的文章主要介绍了Java21来了,赶紧用起来(附代码使用示例)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

1 官网下载

https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html

2 简介

官方简介: https://www.oracle.com/cn/java/
官方更新内容简介:https://openjdk.org/projects/jdk/21/
官方博客介绍:https://blogs.oracle.com/java/post/the-arrival-of-java-21

Java21 自发布日起,将会长期支持 8 年。(长期维护更新,修复bug)
相当于当年的 java8 ,预计会很受 java 程序员的喜欢。

一、Java 21 的特性 -Project Amber

Project Amber是Java和OpenJDK开发人员当前的一项举措,旨在为JDK提供一些细微但必不可少的更改,以使开发过程变得更好。 自2017年以来一直在进行,这些更新都以JEP的形式打包在一起-JDK增强建议方案。

1 字符串模板

JEP 430: String Templates (Preview)

1.1 功能描述

此功能的目的在于以下几点:

  • 简化书写,使得包含在运行时计算的值得字符串更容易表达出来;
  • 增强混合文本和表达式的表达式的可读性,涉及到单行字符串和多行字符串;
  • 通过支持模板及其嵌入表达式的值的验证和转换,提高Java程序的安全性,这些程序从用户提供的值组成字符串并将其传递给其他系统(例如,为数据库构建查询,拼接sql语句);
  • 通过允许Java库定义字符串模板中使用的格式化语法来保持灵活性;
  • 简化接受用非Java语言(如SQL、XML和JSON)编写的字符串的API的使用,比如构造json模板,然后注入动态变量;
  • 允许创建根据文字文本和嵌入表达式计算的非字符串值,而无需通过中间字符串表示;

1.2 原理简析

核心类是一个lang包下的接口 StringTemplate ,它里边定义了 STR 常量(以及几个类似用途的常量,这里只介绍STR),一般我们直接用这个常量来得到一个字符串即可。

该常量的定义如下:

Processor<String, RuntimeException> STR = StringTemplate::interpolate;

1.3 代码示例

最简单的用法如下:

String name = "Joan";
String info = STR."My name is \{name}";
assert "My name is Joan".equals(info);   // true

int x = 10;
int y = 20;
String result = STR."\{x} + \{y} = \{x + y}";
System.out.println(result); // 10 + 20 = 30

另外,在写法上,也可以嵌入数组,方法等内容,如下示例:

// 定义一个点,拥有坐标 x,y
record Point(int x, int y) {
        /**
         * 计算两点间距离
         *
         * @param start 起点坐标
         * @param end   终点坐标
         * @return 距离值
         */
        public static BigDecimal calcDistance(Point start, Point end) {
            return BigDecimal.valueOf(Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)));
        }
}


public static void main(String[] args) {

        Point start = new Point(0, 0);
        Point end = new Point(3, 4);
        Point[] pointArray = new Point[]{start, end};
        String desc = STR. "起点是\{ pointArray[0] } 终点是 \{ pointArray[1] }" ;
        String startDesc = STR. "起点坐标是(\{ pointArray[0].x }, \{ pointArray[0].y })" ;
        String endDesc = STR. "终点坐标是(\{ pointArray[1].x }, \{ pointArray[1].y })" ;

        String multiLineDesc = STR. """
                起点坐标是(\{ pointArray[0].x }, \{ pointArray[0].y })
                终点坐标是(\{ pointArray[1].x }, \{ pointArray[1].y })
                他们之间的距离是\{Point.calcDistance( pointArray[0],  pointArray[1])}
                """ ;

        System.out.println(desc);
        System.out.println(startDesc);
        System.out.println(endDesc);
        System.out.println("----multiLineDesc----");
        System.out.println(multiLineDesc);
}

输出结果如下:

起点是Point[x=0, y=0] 终点是 Point[x=3, y=4]
起点坐标是(0, 0)
终点坐标是(3, 4)
----multiLineDesc----
起点坐标是(0, 0)
终点坐标是(3, 4)
他们之间的距离是5.0

另外按照这样的思路,我们可以构建 xml 、json等格式的字符串出来:

// 定义人
record People(int id, String name, int age, LocalDate birthday) {}

People people = new People(1, "小刘", 27, LocalDate.of(1996, 4, 1));
String json = STR."""
        {
            "id": \{people.id},
            "birthday": "\{ DateTimeFormatter.ofPattern("yyyy-MM-dd").format(people.birthday)}"
        }
        """;
System.out.println(json);

打印结果如下:

{
    "id": 1,
    "birthday": "1996-04-01"
}

2 记录模式匹配

JEP 440: Record Patterns

本质上是对模式匹配的一种扩展,支持了记录类型的匹配,以及增强功能。

2.1 代码示例

早先的写法:

/**定义动物类*/
static class Animal {}
/**定义狗类,继承动物*/
static class Dog extends Animal {}

// 之前的模式匹配
Animal animal = new Dog();
if(animal instanceof Dog) {
    Dog dog = (Dog) animal;
    System.out.println(dog);
}
// 可定义变量名的版本
if(animal instanceof Dog dog) {
    System.out.println(dog);
}

record 的模式匹配:

// 定义人
record People(int id, String name, int age, LocalDate birthday) {}

People people = new People(1, "小刘", 27, LocalDate.of(1996, 4, 1));
// record 的模式匹配
Object someone = people;
if(someone instanceof People people1) {
    System.out.println(people1);
}
if(someone instanceof People(int id, String name, int age, LocalDate birthday)) {
   System.out.println(STR."\{name}的生日是\{DateTimeFormatter.ofPattern("yyyy-MM-dd").format(birthday)}");
}

输出结果如下:

People[id=1, name=小刘, age=27, birthday=1996-04-01]
小刘的生日是1996-04-01

3 switch 模式匹配

JEP 441: Pattern Matching for switch

这里的switch语句变动挺大的,涉及到case null ,以及枚举,还有Object类型。也就是说case中可以更加灵活了。

3.1 代码示例 switch任意类型

    public static int switchTest(Object object) {
        return switch (object) {
            case null -> 0;
            case Integer num ->  num;
            case Double num -> BigDecimal.valueOf(num).intValue();
            case Long num -> num.intValue();
            case String str when "yes".equals(str) -> 1;
            case String str when "no".equals(str) -> 0;
            default -> 0;
        };
    }

执行结果:

System.out.println(switchTest(null)); // 0
System.out.println(switchTest(21312L)); // 21312
System.out.println(switchTest(12131)); // 12131
System.out.println(switchTest(1.2313123)); // 1
System.out.println(switchTest("yes")); // 1
System.out.println(switchTest("no")); // 0

3.2 代码示例 switch 字符串

public static int switchTestString(String str) {
    return switch (str) {
        case null -> 0;
        case "y", "Y" -> 1;
        case "n", "N" -> 0;
        default -> 0;
    };
}

执行结果:

System.out.println(switchTestString("y")); // 1
System.out.println(switchTestString("Y")); // 1
System.out.println(switchTestString("n")); // 0
System.out.println(switchTestString("N")); // 0

3.3 代码示例 switch 接口

示例来自官网
先定义接口,以及实现类:

// 定义接口,并指定有两个实现类
sealed interface CardClassification permits Suit, Tarot {}
public enum Suit implements CardClassification { CLUBS, DIAMONDS, HEARTS, SPADES }
static final class Tarot implements CardClassification {}

然后进行匹配:


    public static void testSwitchEnum(CardClassification enumObject) {
        switch (enumObject) {
            case Suit s when s == Suit.CLUBS -> {
                System.out.println("It's clubs");
            }
            case Suit s when s == Suit.DIAMONDS -> {
                System.out.println("It's diamonds");
            }
            case Suit s when s == Suit.HEARTS -> {
                System.out.println("It's hearts");
            }
            case Suit s -> {
                System.out.println("It's spades");
            }
            case Tarot t -> {
                System.out.println("It's a tarot");
            }
        }
    }

执行结果:

testSwitchEnum(Suit.CLUBS); // It's clubs
testSwitchEnum(Suit.DIAMONDS); // It's diamonds
testSwitchEnum(new Tarot()); // It's a tarot

3.4 代码示例 处理null

定义处理null和不处理null的switch,进行对比。

public static void dealNullSwitch(Object object){
    switch (object) {
        case null -> System.out.println("null");
        default -> System.out.println("default");
    }
}


public static void withoutDealNullSwitch(Object object){
    switch (object) {
        default -> System.out.println("default");
    }
}

执行结果:不处理时,会抛出空指针异常

dealNullSwitch(null); // null
withoutDealNullSwitch(null); // 抛空指针异常

4 匿名模式匹配和变量

JEP 443: Unnamed Pattern and Variable (Preview)

在使用模式匹配时,我们或许会遇到用不着的变量,但又因为语法规则,必须给他们定义出来。
现在就不必了,可以简化我们的一些操作。
其实在官方的 jep文档中,也有不少示例,我这里自己写了下我认为可能会经常用到的。

比如,可以用在for循环中,可以用在try catch 块中。

4.1 代码示例

先定义几个记录类,用于演示。

/**
     * 长方形
     *
     * @param length 长
     * @param width  宽
     */
    record Rectangle(int length, int width) implements Graphical {
        @Override
        public BigDecimal getArea() {
            return BigDecimal.valueOf((long) length * width);
        }
    }

    /**
     * 正方形
     *
     * @param length 边长
     */
    record Square(int length) implements Graphical {
        @Override
        public BigDecimal getArea() {
            return BigDecimal.valueOf((long) length * length);
        }
    }

    /**
     * 圆
     *
     * @param radius 半径
     */
    record Circle(int radius) implements Graphical {
        @Override
        public BigDecimal getArea() {
            return BigDecimal.valueOf(Math.PI * radius * radius);
        }
    }

    /**
     * 定义图形接口,并指定3个实现类
     */
    sealed interface Graphical permits Rectangle, Square, Circle {
        /**
         * 计算面积
         *
         * @return 面积
         */
        BigDecimal getArea();
    }

然后依据以上的接口和record,使用匿名方式做验证:

public static void main(String[] args) {

        Graphical g1 = new Rectangle(10, 20);
        Graphical g2 = new Square(5);
        Graphical g3 = new Circle(5);

        Graphical[] graphicalArray = new Graphical[]{g1, g2, g3};

        // switch case 模式匹配中的匿名变量
        for (Graphical graphical : graphicalArray) {
            switch (graphical) {
                case null -> System.out.println("null");
                // 不需要用到的变量,可以用下划线代替
                case Rectangle(int length, _) -> System.out.println(STR."长方形的长是 \{length}");
                case Circle(_) -> System.out.println(STR."圆的面积是\{graphical.getArea()}");
                default -> System.out.println("default");
            }
        }

        // instanceof 时的匿名变量
        if(g1 instanceof Rectangle(_, int width)) {
            System.out.println(STR."长方形的宽是\{width}, 面积是\{g1.getArea()}");
        }

        // for循环中的匿名变量
        int graphicalCount = 0;
        for (Graphical _ : graphicalArray) {
            graphicalCount ++;
        }
    }

5 匿名类和实例main方法

JEP 445: Unnamed Classes and Instance Main Methods (Preview)

这是一个预览的功能,默认禁用。其实就是简化了下main方法,实际开发没啥大用。

 void main() { 
        System.out.println("Hello, World!");
    }

PS :我本地实验的时候,发现idea即使最新版,也不能直接执行它。就放弃了。

二、Java 21 的特性 -Project Loom

探索新的Java语言特性、API和轻量级并发的运行时-包括虚拟线程的新构造

1 虚拟线程

JEP 444: Virtual Threads

现在的虚拟线程可以通过线程框架来创建了, 并且支持了 threadlocal变量。

Executors.newVirtualThreadPerTaskExecutor()

1.1 基本概念

在jep的描述中,有这样一段话:

Today, every instance of java.lang.Thread in the JDK is a platform thread.
 A platform thread runs Java code on an underlying OS thread and captures the OS thread for the code's entire lifetime.
The number of platform threads is limited to the number of OS threads.

A virtual thread is an instance of java.lang.Thread that runs Java code on an underlying OS thread but does not capture the OS thread for the code's entire lifetime. This means that many virtual threads can run their Java code on the same OS thread, effectively sharing it. 
While a platform thread monopolizes a precious OS thread, a virtual thread does not. 
The number of virtual threads can be much larger than the number of OS threads.

Virtual threads are a lightweight implementation of threads that is provided by the JDK rather than the OS. They are a form of user-mode threads, which have been successful in other multithreaded languages (e.g., goroutines in Go and processes in Erlang).
  User-mode threads even featured as so-

大致含义是:
如今,JDK中java.lang.Thread的每个实例都是一个平台线程。平台线程在底层操作系统线程上运行Java代码,并在代码的整个生命周期中捕获操作系统线程。平台线程的数量限制为操作系统线程的数量。

虚拟线程是java.lang.thread的一个实例,它在底层操作系统线程上运行java代码,但在代码的整个生命周期内不会捕获该操作系统线程。这意味着许多虚拟线程可以在同一个操作系统线程上运行Java代码,从而有效地共享代码。虽然平台线程独占了宝贵的操作系统线程,但虚拟线程却没有。虚拟线程的数量可以比操作系统线程的数量大得多。

虚拟线程是JDK而不是OS提供的线程的轻量级实现。它们是用户模式线程的一种形式,在其他多线程语言中也很成功(例如Go中的goroutines和Erlang中的processes)。用户模式线程也是如此。

官方建议,虚拟线程不要被池化。

1.2 Thread API 的更新

  • 创建虚拟线程:
    Thread.Builder, Thread.ofVirtual(), and Thread.ofPlatform()
    比如:Thread thread = Thread.ofVirtual().name("duke").unstarted(runnable);

  • 创建并启动虚拟线程:Thread.startVirtualThread(Runnable)
    Thread.Builder 可以建造线程或线程工厂。

  • 判断线程是否是虚拟线程:Thread.isVirtual()

1.3 代码示例

这个在使用时,写的代码比较简单,我这里直接粘贴了官方文档中的示例:

void handle(Request request, Response response) {
    var url1 = ...
    var url2 = ...
 
    try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        var future1 = executor.submit(() -> fetchURL(url1));
        var future2 = executor.submit(() -> fetchURL(url2));
        response.send(future1.get() + future2.get());
    } catch (ExecutionException | InterruptedException e) {
        response.fail(e);
    }
}
 
String fetchURL(URL url) throws IOException {
    try (var in = url.openStream()) {
        return new String(in.readAllBytes(), StandardCharsets.UTF_8);
    }
}

2 作用域值

JEP 446: Scoped Values (Preview)

待完善

3 结构化并发

JEP 453: Structured Concurrency (Preview)

三、Java 21 的特性 -Project Panama

主要涉及Java与外部api的交互。比如C语言。

这一部分本人目前为止没咋用过,就不研究了,脑容量有限。

四、Java 21 的特性 -核心库

1 序列化集合

JEP 431: Sequenced Collections

五、Java 21 的特性 -性能更新

1 分代 ZGC

JEP 439: Generational ZGC

2 密钥封装机制api

JEP 452: Key Encapsulation Mechanism API

六、维护和弃用

1 弃用Windows 32位x86端口

JEP 449: Deprecate the Windows 32-bit x86 Port for Removal

2 禁止动态加载代理

JEP 451: Prepare to Disallow the Dynamic Loading of Agents文章来源地址https://www.toymoban.com/news/detail-783554.html

到了这里,关于Java21来了,赶紧用起来(附代码使用示例)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java geotools库代码示例:使用Geotools库来读取和显示Shapefile文件(GIS java常用库示例)

    Geotools是一个开源的Java库,用于处理和分析地理空间数据,并提供了一组工具和API,以便在Java应用程序中使用地理空间数据。它是一个成熟的GIS库,具有广泛的功能和支持,可用于多种应用场景,包括地图制作、数据分析、空间查询和可视化等。 以下是Geotools库的一些主要特

    2024年02月04日
    浏览(36)
  • 使用Java Swing绘制字符串描边的示例代码

    我最近在工作的实际开发中,遇到了一个需求,给字符串描边,无从那个下手,最终请教了代码生成的AI工具,把这个需求实现了,在次记录供大家参考, 我解决问题之后,觉得还是把这些坑都写清楚,方便 大家少踩坑呢。 此代码有该AI 助手为您带来的,v信小程序:

    2024年02月16日
    浏览(28)
  • 中文分词入门:使用IK分词器进行文本分词(附Java代码示例)

    中文分词是将连续的中文文本切分成一个个独立的词语的过程,是中文文本处理的基础。IK分词器是一个高效准确的中文分词工具,采用了\\\"正向最大匹配\\\"算法,并提供了丰富的功能和可定制选项。 细粒度和颗粒度的分词模式选择。 可自定义词典,提高分词准确性。 支持中文

    2024年02月17日
    浏览(48)
  • java基础知识——21.内部类

    这篇文章,我们来介绍一下java的内部类知识 目录 1.内部类介绍 1.1内部类的应用场景 1.2 小结 2.成员内部类 2.1 成员内部类的书写 2.2 创建成员内部类的对象 2.3 成员内部类获取外部类的成员变量 3.静态内部类 4.局部内部类 5.匿名内部类 6.总结 首先,我们来介绍一下,什么是内

    2023年04月08日
    浏览(26)
  • 【Java基础教程】特别篇:面向对象合辑——掀开Java 的面向对象盖章时代,一起来发现OOP的编程秘密!~

    面向对象编程(Object-Oriented Programming, OOP)是一种广泛应用于软件开发的编程范式 。Java是一种面向对象的编程语言,它提供了丰富的工具和特性来支持面向对象编程。本文将详细介绍Java面向对象的全部知识。 我们可以把一个Java类想象成是一个蓝图或者模具,用来创建对象。就

    2024年02月17日
    浏览(38)
  • 【Java基础系列】JDK21新特性

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月04日
    浏览(36)
  • 【Java基础-JDK21新特性】它发任它发,我用java8

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月08日
    浏览(35)
  • 教你用Midjourney做UI,设计们赶紧学起来!

    在AI绘画的大浪潮下,很多朋友开始尝试使用Midjourney做 UI 设计,我这边就从APP活动弹窗、福袋活动弹窗、直播礼物元素、3D活动弹窗、B端运营海报这几方面来做实操演示。这篇先来说说“APP活动弹窗”的设计方法。 大家在接到设计需求后,应该都会根据需求找对应的参考图

    2024年01月23日
    浏览(34)
  • 30个AI变现案例,太全了,赶紧实操起来

    精心整理了30个AI变现案例,每一个都可以作为一个完整的副业去实践,AI时代已经来了,所有不甘于现状的朋友,都应该去下场,先把手弄脏,不要怕,实践起来! 项目: Al技术手剧本创作商单 市场分析: 客户群体: 需求简单、成本敏感的商单, 适合Al剧本创作, 可以实

    2024年04月12日
    浏览(23)
  • 5G 时代来了;还不赶紧学习音视频?

    随着 5G 时代的到来 , 移动技术 的发展不仅带来 网速的提升 ,同时也推动 流量单位成本下降 , 企业通信方式 从 文本消息 到 富媒体消息 ,如今也逐渐向 实时高清音视频升级 ; 防护 工作的持续使得 视频会议、远程办公、线上教学 成为许多人工作中的**“常态” ;对于

    2023年04月14日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包