JDK14新特征最全详解

news2024/9/21 10:37:14

JDK 14一共发行了16个JEP(JDK Enhancement Proposals,JDK 增强提案),筛选出JDK 14新特性。

- 343: 打包工具 (Incubator)

- 345: G1的NUMA内存分配优化

- 349: JFR事件流

- 352: 非原子性的字节缓冲区映射

- 358: 友好的空指针异常

- 359: Records (预览)

- 361: Switch表达式 (标准)

- 362: 弃用Solaris和SPARC端口

- 363: 移除CMS(Concurrent Mark Sweep)垃圾收集器

- 364: macOS系统上的ZGC

- 365: Windows系统上的ZGC

- 366: 弃用ParallelScavenge + SerialOld GC组合

- 367: 移除Pack200 Tools 和 API

- 368: 文本块 (第二个预览版)

- 370: 外部存储器API (Incubator)

1 JEP 305的instanceof运算符

JEP 305新增使instanceof运算符具有模式匹配的能力。模式匹配使程序通用逻辑更简洁,代码更简单,同时在做类型判断和类型转换时也更安全。

设计初衷

包含判断表达式是否具有某种类型的逻辑时,程序会对不同类型进行不同的处理。

instanceof-and-cast

// 在方法的入口接收一个对象
public void beforeWay(Object obj) {
    // 通过instanceof判断obj对象的真实数据类型是否是String类型
    if (obj instanceof String) {
        // 如果进来了,说明obj的类型是String类型,直接进行强制类型转换。
        String str = (String) obj;
        // 输出字符串的长度
        System.out.println(str.length());
    }
}
  1. 先判断obj的真实数据类型
  2. 判断成立后进行了强制类型转换(将对象obj强制类型转换为String)
  3. 声明一个新的本地变量str,指向上面的obj

但上述做法不是最理想:

  • 语法臃肿乏味
  • 同时执行类型检测校验和类型转换
  • String类型出现3次,但最终要的可能只是一个String类型的对象变量
  • 重复代码过多,冗余度高

JDK14提供新解决方案:新的instanceof模式匹配 ,用法如下,在instanceof的类型之后添加变量str

instanceofobj的类型检查通过,obj会被转换成str表示的String类型。在新用法中,String类型仅出现一次:

public void patternMatching(Object obj) {
    if (obj instanceof String str) {
          // can use str here
        System.out.println(str.length());
    } else {
        // can't use str here
    }
}

注意:若obj是String类型,则将obj类型转换为String,并将其赋值给变量str。绑定的变量作用域为if语句内部,并不在false语句块内。

简化equals()

equals()一般先检查目标对象的类型。instanceof的模式匹配可简化equals()实现。

public class Student {
  private  String name ;

  public Student(String name) {
    this.name = name;
  }

//    @Override
//    public boolean equals(Object o) {
//        if (this == o) return true;
//        if (o == null || getClass() != o.getClass()) return false;
//        Student student = (Student) o;
//        return Objects.equals(name, student.name);
//    }
  // 简化后做法!  
  @Override
  public boolean equals(Object obj) {
    return (obj instanceof Student s) && Objects.equals(this.name, s.name);
  }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

JDK 14后的instanceof的模式匹配极大的简化了类型检查和转型的问题。

2 JEP 361:Switch Expressions (Standard)

扩展switch分支选择语句的写法。Switch表达式在经过JDK 12(JEP 325)和JDK(JEP 354)的预览之后,在JDK 14中已稳定可用。

2.1 设计初衷

switch语句是个变化较大的语法。可是因为Java switch一直不够强大、熟悉swift或js语言的同学可对比发现,因为Java的很多版本都在不断改进switch语句:JDK 12扩展了switch语句,使其可用作语句或表达式,并且传统的和扩展的简化版switch都可以使用。

JDK 12对于switch的增强主要在于简化书写形式,提升功能点。

2.2 switch的进化

  • Java 5+开始,可用枚举
  • Java 7+开始,支持使用String类型的变量和表达式
  • Java 11+开始,自动对省略break导致的贯穿提示警告(以前需用-X:fallthrough选项才能显示)

从JDK12开始有大程度增强,JDK 14的该JEP是从JEP 325和JEP 354演变而来。但是,此JEP 361 Switch表达式 (标准)是独立的,并不依赖于这俩JEP。

2.3 以前的switch程序

public class Demo01 {
    public static void main(String[] args){
        // 声明变量score,并为其赋值为'C'
        var score = 'C';
        // 执行switch分支语句
        switch (score) {
            case 'A':
                System.out.println("优秀");
                break;
            case 'B':
                System.out.println("良好");
                break;
            case 'C':
                System.out.println("中");
                break;
            case 'D':
                System.out.println("及格");
                break;
            case 'E':
                System.out.println("不及格");
                break;
            default:
                System.out.println("数据非法!");
        }
    }
}

经典的Java 11前的写法 ,不能忘写break,否则switch就会贯穿、导致程序出现错误(JDK 11会提示警告)。

2.4 无需break

在JDK 12前switch忘写break将导致贯穿,在JDK 12对switch的这一贯穿性做了改进。只要将case后面的":"改成箭头,即使不写break也不会贯穿,因此上面程序可改写为:

public class Demo02{
    public static void main(String[] args){
        // 声明变量score,并为其赋值为'C'
        var score = 'C';
        // 执行switch分支语句
        switch (score){
            case 'A' -> System.out.println("优秀");
            case 'B' -> System.out.println("良好");
            case 'C' -> System.out.println("中");
            case 'D' -> System.out.println("及格");
            case 'E' -> System.out.println("不及格");
            default -> System.out.println("成绩数据非法!");
        }
    }
}

简洁很多了。注意,新老语法不能混用了,否则编译报错:

java: 在 switch 中使用了不同 case 类型:

2.5 JDK 14的switch表达式

JDK 12后的switch甚至可作为表达式,不再是单独的语句,如:

public class Demo03 {
    public static void main(String[] args) {
        // 声明变量score,并为其赋值为'C'
        var score = 'C';
        // 执行switch分支语句
        String s = switch (score)
                {
                    case 'A' -> "优秀";
                    case 'B' -> "良好";
                    case 'C' -> "中";
                    case 'D' -> "及格";
                    case 'F' -> "不及格";
                    default -> "成绩输入错误";
                };
        System.out.println(s);
    }
}

上面程序直接将switch表达式的值赋值给s变量,这样switch不再是一个语句,而是一个表达式。

2.6 多值匹配

当你把switch中的case后的冒号改为箭头之后,此时switch就不会贯穿,但某些情况,程序本就希望贯穿。比如希望两个case共用一个执行体!

JDK 12之后的switch中的case也支持多值匹配,这样程序就变得更加简洁了,如:

public class Demo04 {
    public static void main(String[] args) {
                 // 声明变量score,并为其赋值为'C'
        var score = 'B';

        // 执行switch分支语句
        String s = switch (score)
                {
                    case 'A', 'B' -> "上等";
                    case 'C' -> "中等";
                    case 'D', 'E' -> "下等";
                    default -> "成绩数据输入非法!";
                };
        System.out.println(s);
    }
}

2.7 Yielding a value

用箭头标签时,箭头标签右边可为表达式、throw语句或是代码块。

如是代码块,需用yield语句来返回值。下面代码中的print方法中的default语句的右边是一个代码块。在代码块中使用yield来返回值。

JDK 14引入yield语句产生一个值,该值成为封闭的switch表达式的值。

public void print(int days) {
  // 声明变量score,并为其赋值为'C'
  var score = 'B';
  String result = switch (score) {
      case 'A', 'B' -> "上等";
      case 'C' -> "中等";
      case 'D', 'E' -> "下等";
      default -> {
          if (score > 100) {
            yield "数据不能超过100";
          } else {
            yield score + "此分数低于0分";
          }
      }
  };
  System.out.println(result);
}

在switch表达式中不能使用break。switch表达式的每个标签都必须产生一个值或抛异常。

switch表达式须穷尽所有可能值。这意味着通常需要一个default语句。一个例外是枚举类型,如穷尽了枚举类型的所有可能值,则不需要使用default。在这种情况下,编译器会自动生成一个default语句。这是因为枚举类型中的枚举值可能发生变化。

如枚举类型Color 中原来只有3个值:RED、GREEN和BLUE。使用该枚举类型的switch表达式穷尽了3种情况并完成编译。之后Color中增加了一个新的值YELLOW,当用这个新的值调用之前的代码时,由于不能匹配已有的值,编译器产生的default会被调用,告知枚举类型发生改变

3 JEP 368:文本块 (JDK 13后的第二个预览版)

3.1 引入

Java开发通常需进行大量字符串文本拼接等相关组织操作,从JDK 13到JDK 14开始文本块新特性,提高Java程序书写大段字符串文本的可读性和方便性。

3.2 设计初衷

文本块功能在JDK 13中作为预览功能(JEP 355)被引入。这个功能在JDK 14中得到了更新。文本块是使用3个引号分隔的多行字符串。

3.3 描述

文本块可表示任何字符串,具有更高表达能力和更少复杂度。

文本块开头定界符是("""),后面跟0或多个空格,最后跟一个行终止符。内容从开头定界符的行终止符之后的第一个字符开始。结束定界符也是(""")。内容在结束定界符的第一个双引号之前的最后一个字符处结束。

与字符串文字中的字符不同,文本块的内容中可以直接包含双引号字符。当然也允许在文本块中使用\“,但不是必需也不建议用。与字符串文字中的字符不同,内容可以直接包含行终止符。允许在文本块中用\n,但不是必需也不建议用。

如文本块:

line 1
line 2
line 3

就等效于字符串文字:

"line 1\nline 2\nline 3\n"

或字符串文字的串联:

"line 1\n" +
"line 2\n" +
"line 3\n"

文本块功能在JDK 13中作为预览功能(JEP 355)被引入。这个功能在JDK 14中得到了更新。文本块是使用3个引号分隔的多行字符串。根据文本块在源代码中的出现形式,多余的用于缩进的白字符会被去掉。相应的算法会在每一行中去掉同样数量的白字符,直到其中任意的一行遇到非白字符为止。每一行字符串末尾的白字符会被自动去掉。

下面代码中的文本块xml会被去掉前面的2个白字符的缩进。

String xml = """
  <root>
    <a>Hello</a>
    <b>
      <c>
        <d>World</d>
      </c>
    </b>
  </root>
  """;

缩进的去除是要考虑到作为结束分隔符的3个引号的位置的。如果把上面的文本块改成下面代码的格式,则没有缩进会被去掉。注意最后一行中3个引号的位置。去除的白字符的数量需要考虑到全部行中前导的白字符数量,包括最后一行。最终去除的白字符数量是这些行中前导白字符数量的最小值。

String xml2 = """
  <root>
    <a>Hello</a>
    <b>
      <c>
        <d>World</d>
      </c>
    </b>
  </root>
""";

在文本块中同样可以使用\n和\r这样的转义字符。除了String本身支持的转义字符之外,文本块还支持2个特殊的转义字符:

- \:阻止插入换行符。

- \s:表示一个空格。可以用来避免末尾的白字符被去掉。

由于\的使用,下面代码中的longString实际上只有一行。

String longString = """
    hello \
    world \
    goodbye
    """;

在下面的代码中,通过使用\s,每一行的长度都为10。

String names = """
    alex     \s
    bob      \s
    long name\s
    """;

3.4 HTML

使用原始字符串语法:

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world</p>\n" +
              "    </body>\n" +
              "</html>\n";

使用文本块文本块语法:

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;

3.5 SQL

原始的字符串语法:

String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
               "WHERE `CITY` = 'INDIANAPOLIS'\n" +
               "ORDER BY `EMP_ID`, `LAST_NAME`;\n";

文本块语法:

String query = """
               SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
               WHERE `CITY` = 'INDIANAPOLIS'
               ORDER BY `EMP_ID`, `LAST_NAME`;
               """;

3.6 多语言示例

原始字符串语法:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("function hello() {\n" +
                         "    print('\"Hello, world\"');\n" +
                         "}\n" +
                         "\n" +
                         "hello();\n");

文本块语法:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Object obj = engine.eval("""
                         function hello() {
                             print('"Hello, world"');
                         }

                         hello();
                         """);

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化

  • 活动&券等营销中台建设

  • 交易平台及数据中台等架构和开发设计

  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化

  • LLM Agent应用开发

  • 区块链应用开发

    目前主攻市级软件项目设计、构建服务全社会的应用系统。

参考:

  • 编程严选网

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1925647.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

游戏的无边框模式是什么?有啥用?

现在很多游戏的显示设置中&#xff0c;都有个比较特殊的选项“无边框”。小伙伴们如果尝试过&#xff0c;就会发现这个效果和全屏几乎一毛一样&#xff0c;于是就很欢快地用了起来&#xff0c;不过大家也许会发现&#xff0c;怎么和全屏比起来&#xff0c;似乎有点不够爽快&…

单例模式Singleton

设计模式 23种设计模式 Singleton 所谓类的单例设计模式&#xff0c;就是采取一定的方法保证在整个的软件系统中&#xff0c;对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法。 饿汉式 public class BankTest {public static void main(…

[图解]SysML和EA建模住宅安全系统-14-黑盒系统规约

1 00:00:02,320 --> 00:00:07,610 接下来&#xff0c;我们看下一步指定黑盒系统需求 2 00:00:08,790 --> 00:00:10,490 就是说&#xff0c;把这个系统 3 00:00:11,880 --> 00:00:15,810 我们的目标系统&#xff0c;ESS&#xff0c;看成黑盒 4 00:00:18,030 --> …

Kafka基础入门篇(深度好文)

Kafka简介 Kafka 是一个高吞吐量的分布式的基于发布/订阅模式的消息队列&#xff08;Message Queue&#xff09;&#xff0c;主要应用与大数据实时处理领域。 1. 以时间复杂度为O(1)的方式提供消息持久化能力。 2. 高吞吐率。&#xff08;Kafka 的吞吐量是MySQL 吞吐量的30…

数据结构初阶(C语言)-复杂度的介绍

在学习顺序表之前&#xff0c;我们需要先了解下什么是复杂度&#xff1a; 一&#xff0c;复杂度的概念 我们在进行代码的写作时&#xff0c;通常需要用到许多算法&#xff0c;而这些算法又有优劣之分&#xff0c;区分算法的优劣则是通过算法的时间复杂度和空间复杂度来决定。 …

【眼疾病识别】图像识别+深度学习技术+人工智能+卷积神经网络算法+计算机课设+Python+TensorFlow

一、项目介绍 眼疾识别系统&#xff0c;使用Python作为主要编程语言进行开发&#xff0c;基于深度学习等技术使用TensorFlow搭建ResNet50卷积神经网络算法&#xff0c;通过对眼疾图片4种数据集进行训练&#xff08;‘白内障’, ‘糖尿病性视网膜病变’, ‘青光眼’, ‘正常’&…

Python+wxauto=微信自动化?

Pythonwxauto微信自动化&#xff1f; 一、wxauto库简介 1.什么是wxauto库 wxauto是一个基于UIAutomation的开源Python微信自动化库。它旨在帮助用户通过编写Python脚本&#xff0c;轻松实现对微信客户端的自动化操作&#xff0c;从而提升效率并满足个性化需求。这一工具的出现&…

SAP PP学习笔记26 - User Status(用户状态)的实例,订单分割中的重要概念 成本收集器,Confirmation(报工)的概述

上面两章讲了生产订单的创建以及生产订单的相关内容。 SAP PP学习笔记24 - 生产订单&#xff08;制造指图&#xff09;的创建_sap 工程外注-CSDN博客 SAP PP学习笔记25 - 生产订单的状态管理(System Status(系统状态)/User Status(用户状态)),物料的可用性检查&#xff0c;生…

语音识别概述

语音识别概述 一.什么是语音&#xff1f; 语音是语言的声学表现形式&#xff0c;是人类自然的交流工具。 图片来源&#xff1a;https://www.shenlanxueyuan.com/course/381 二.语音识别的定义 语音识别&#xff08;Automatic Speech Recognition, ASR 或 Speech to Text, ST…

数字探秘:用神经网络解密MNIST数据集中的数字!

用神经网络解密MNIST数据集中的数字&#xff01; 一. 介绍1.1 MNIST数据集简介1.2 MLP&#xff08;多层感知器&#xff09;模型介绍1.3 目标&#xff1a;使用MLP模型对MNIST数据集中的0-9数字进行分类 二.数据预处理2.1 数据集的获取与加载2.2 数据集的探索性分析&#xff08;E…

编写商品列表和商品编辑和商品新增页面

addvue <template><!-- 传过来的id --> <!-- {{ $route.query.id }} --> <el-formref"FormRef"style"max-width: 600px":model"FormData":rule"rules"status-iconlabel-width"auto"class"demo-r…

【中台】数字中台建设方案(PPT)

数字中台建设要点&#xff1a; 数据采集与整合&#xff1a; 打破企业内部各个业务系统的数据隔阂&#xff0c;通过数据采集和数据交换实现数据的集中管理&#xff0c;形成统一的数据中心&#xff0c;为后续数据价值的挖掘提供基础。 利用自研或第三方ETL&#xff08;Extract, T…

最长下降序列

如何理解这个题目呢,我们可以每个人的分数放到排名上&#xff0c;然后求解最长下降序列即可 #include<bits/stdc.h> using namespace std;int n; const int N (int)1e5 5; int a[N]; int b[N]; int d[N]; int dp[N]; int t;int main() {cin >> t;while (t--) {…

排序——归并排序及排序章节总结

前面的文章中 我们详细介绍了排序的概念&#xff0c;插入排序&#xff0c;交换排序与选择排序&#xff0c;大家可以通过下面的链接再去学习&#xff1a; ​​​​​​排序的概念及插入排序 交换排序 选择排序 这篇文章就详细介绍一下另一种排序算法&#xff1a;归并排序以及…

PE文件(十)重定位表

重定位表的引入 程序加载过程 在win32下&#xff0c;每一个PE文件&#xff08;其可能由多个子PE文件组成&#xff09;在运行时&#xff0c;操作系统会给分配一个独立的4GB虚拟内存&#xff0c;内存地址从0x00000000到0xFFFFFFFF。其中低2G为用户程序空间&#xff0c;高2G为操…

【Linux】进程间通信——消息队列和信号量

目录 消息队列&#xff08;message queue&#xff09; 信号量&#xff08;Semaphore&#xff09; system V版本的进程间通信方式有三种&#xff1a;共享内存&#xff0c;消息队列和信号量。之前我们已经说了共享内存&#xff0c;那么我们来看一下消息队列和信号量以及它们之间…

【鸿蒙学习笔记】位置设置・position・绝对定位

官方文档&#xff1a;位置设置 目录标题 position&#xff1a;绝对定位&#xff0c;确定子组件相对父组件的位置。 position&#xff1a;绝对定位&#xff0c;确定子组件相对父组件的位置。 正→ ↓ Entry Component struct Loc_position {State message: string Hello Wor…

汇编语言程序设计-8-汇编语言快速查阅

8. 汇编语言快速查阅 文章目录 8. 汇编语言快速查阅常用资料寄存器含义标志寄存器的含义Debug的使用汇编语法 本章列出一些需要经常查阅的知识点。 常用资料 参考视频&#xff1a;烟台大学贺利坚老师的网课《汇编语言程序设计系列专题》&#xff0c;或者是B站《汇编语言程序设计…

vue学习day08-v-model详解、sync修饰符、ref和$refs获取dom组件、Vue异步更新和$nextTick

25、v-model详解 &#xff08;1&#xff09;v-model原理 1&#xff09;原理: v-model本质上是一个语法糖&#xff0c;比如&#xff1a;在应用于输入框时&#xff0c;就是value属性与input事件的合写。 2&#xff09;作用 ①数据变&#xff0c;视图变 ②视图变&#xff0c…