2024 可信数据库发展大会报名通道已开启!! 了解详情
写点什么

从 Java 12 到 Java 17 那些激动人心的新特性

作者:Christopher Bielak

  • 2021-12-31
  • 本文字数:4277 字

    阅读完需:约 14 分钟

从Java 12到Java 17那些激动人心的新特性

今日,华为开发者大会正式召开,预示鸿蒙原生应用全新出发!极客时间《鸿蒙 Next 应用开发训练营》,专注鸿蒙原生应用开发,10 周体验真正“纯血”鸿蒙。

2021 年 9 月,Oracle 发布了 Java 17,Java 的下一个长期支持版本。如果你在使用 Java 8 或 Java 11,可能不会注意到 Java 12 之后新增的一些很酷的新特性。


因为这是一个很重要的版本,我会突出介绍一些我个人很感兴趣的新特性!


需要注意的是,Java 中的大多数变更首先需要经过“预览”阶段,也就是说它们被添加到一个版本中,但还没有完成。人们可以尝试使用它们,但不建议将其用在生产环境中。


这里所列举的所有特性都已正式添加到 Java 中,并且已经过了预览阶段。

1:封印类

在 Java 15 中处于预览阶段并在 Java 17 中成为正式特性的封印类,提供了一种新的继承规则限定方法。当你在类或接口前面添加 sealed 关键字的同时,也添加了一个允许扩展这个类或实现这个接口的类的清单。例如,如果你定义了一个类:


public abstract sealed class Color permits Red, Blue, Yellow
复制代码


也就是说,只有 Red、Blue 和 Yellow 可以继承这个类,其他类想要继承它都无法通过编译。


你也可以不使用 permits 关键字,然后将类定义与类放在相同的文件中,如下所示:


public abstract sealed class Color {...}... class Red     extends Color {...}... class Blue    extends Color {...}... class Yellow  extends Color {...}
复制代码


注意,这些子类并不是嵌套在封印类中,而是放在类定义之后。这与使用关键字 permit 是一样的效果,可以扩展 Color 的类只有 Red、Blue 和 Yellow。


那么,封印类通常用在哪里?通过限定继承规则,同时也限定了封装规则。假设你正在开发一个库,并且需要将抽象类 Color 包含在其中。你知道 Color 这个类以及哪些类需要扩展它,但如果它被声明为 public 的,那么你有什么办法可以阻止外部代码扩展它?


如果有人误解了它的用途并用 Square 对它进行了扩展,该怎么办?这符合你的意图吗?或者你其实是想让 Color 保持私有?但即使是这样,包级别的可见性也不能避免所有问题。如果后来有人对这个库进行了扩展了该怎么办?他们如何能够知道你只打算让一小部分类集成 Color?


封印类不仅可以保护你的代码不受外部代码的影响,还是一种向你可能从未见过的人传达意图的方式。如果一个类是封印的,你是在传达只有某些类可以扩展它。这种健壮性可以确保在多年以后任何阅读你代码的人都会理解代码的严谨。

2:增强的空指针异常

增强的空指针异常是一个有趣的更新——不会太复杂,但仍然很受欢迎。这个增强在 Java 14 中正式发布,提高了空指针异常(NullPointerException,简称 NPE)的可读性,可以打印出在抛出异常位置所调用的方法的名称和空变量的名称。例如,如果你调用 a.b.getName(),而 b 为空,那么异常的堆栈跟踪信息会告诉你调用 getName()失败,因为 b 是空的。


我们都知道,NPE 是一种非常常见的异常,虽然在大多数情况下找出导致抛出异常的根源并不难,但你会时不时地遇到同时有两三个可疑变量的情况。你进入调试模式,开始查看代码,但问题很难重现。你只能试着回忆最初做了什么导致抛出 NPE 的。


如果你能提前获得这些信息,就不用这些麻烦地调试了。这就是这个特性的闪光点:不用再猜测 NPE 是从哪里抛出来的。在关键时刻,当你遇到难以重现的异常场景时,你就有了解决问题所需的一切。


这绝对是个救星!

3:switch 表达式

希望你耐心听我说几句——switch表达式(在 Java 12 中预览,并正式添加到 Java 14 中)是 switch 语句和 lambda 之间的某种结合。真的,当我第一次向别人描述 switch 表达式时,我的说法是他们把 switch 语句 lambda 化了。请看下面这个语法:


String adjacentColor = switch (color) {    case Blue, Green    -> "yellow";    case Red, Purple    -> "blue";    case Yellow, Orange -> "red";    default             -> "Unknown Color";};
复制代码


现在明白我的意思了吗?


一个明显的区别是没有了 break 语句。switch 表达式延续了 Oracle 让 Java 语法更简洁的趋势。Oracle 非常讨厌大多数 switch 语句包含很多的 CASE BREAK、CASE BREAK、CASE BREAK……。


老实说,他们讨厌这个是对的,因为人们很容易在这个地方犯错。我们当中是否有人敢说他们从来没有遇到过这种情况:忘记在 switch 里添加 break 语句,只有当代码在运行时发生崩溃才知道?switch 表达式通过一种有趣的方式修复了这个问题,你只需要用逗号隔开同一个代码块里所有的值。没错,不需要使用 break 了!它会替你处理好!


switch 表达式还新增了 yield 关键字。如果一个 case 进入了一个代码块,yield 将被作为 switch 表达式的返回语句。例如,如果我们将上面的代码稍作修改:


String adjacentColor = switch (color) {    case Blue, Green    -> "yellow";    case Red, Purple    -> "blue";    case Yellow, Orange -> "red";    default             -> {    System.out.println("The color could not be found.");    yield "Unknown Color";  }};
复制代码


在默认 case 里,System.out.println()方法将被执行,adjacentColor 变量最终的值是“Unknown Color”,因为这是 yield 返回的结果。


总的来说,switch 表达式是一种更简洁的 switch 语句,但它不会取代 switch 语句,这两种语句都可用。

4:文本块

文本块特性在 Java 13 中预览,并正式添加到 Java 15 中,它可以简化多行字符串的写法,支持换行,并在不需要转义字符的情况下保持缩进。要创建一个文本块,只需要这样:


String text = """HelloWorld""";
复制代码


注意,这个变量仍然是一个字符串,只是它隐含了换行和制表符。同样,如果我们想要使用引号,也不需要转义字符:


String text = """You can "quote" without complaints!"""; // You can "quote" without complaints!
复制代码


唯一需要使用反斜杠转义字符的地方是当你想要在文本块里包含""":


String text = """The only necessary escape is \""",everything else is maintained.""";
复制代码


除此之外,你可以调用 String 的 format()方法,用动态内容替换文本块中的占位符:


String name = "Chris";String text = """My name is %s.""".format(name); // My name is Chris.
复制代码


每行后面的空格都会被剪切掉,除非你指定了'\s',这是文本块的一个转义字符:


String text1 = """No trailing spaces.      Trailing spaces.      \s""";
复制代码


那么,在什么情况下会使用文本块呢?除了能够对大块的文本进行格式化外,将代码片段粘贴到字符串中也变得非常容易。因为缩进被保留了,如果你要写一个 HTML 或 Python 代码块,或使用其他任何语言,你都可以按照正常的方式写好它们,然后用"""把它们括起来,就可以保留代码的格式。你甚至可以用文本块来编写 JSON,并使用 format()方法轻松地插入值。


总的来说,这是个一个很方便的特性。虽然文本块看起来只是一个小功能,但从长远来看,类似这种可以提升开发效率的小功能会逐渐增加。

5:record 类

record类在 Java 14 中预览,并正式添加到 Java 16 中,是一种数据类,处理所有与 POJO 相关的样板代码。也就是说,如果你声明了一个 record 类:


public record Coord(int x, int y) {}
复制代码


equals()和 hashcode()方法会自动实现,toString()将返回这个类实例包含的所有字段的值,最重要的是,x()和 y()将分别返回 x 和 y 的值。想想你之前写过的 POJO 类,并想象一下用 record 类来代替它们会怎样。是不是好看多了?省了多少事了?


除此之外,record 类是 final 和不可变的——不能被继承,并且类实例一旦被创建,它的字段就不能被修改。你可以在 record 类中声明方法,包括非静态方法和静态方法:


public record Coord(int x, int y) {  public boolean isCenter() {    return x() == 0 && y() == 0;  }    public static boolean isCenter(Coord coord) {    return coord.x() == 0 && coord.y() == 0;  }}
复制代码


record 类可以有多个构造器:


public record Coord(int x, int y) {  public Coord() {    this(0,0); // The default constructor is still implemented.  }}
复制代码


需要注意的是,当你在 record 类中声明自定义构造函数时,必须调用默认构造函数。否则,record 类将不知道如何处理它的值。如果你声明了一个与默认构造函数一样的构造函数,你要初始化所有的字段:


public record Coord(int x, int y) {  public Coord(int x, int y) {    this.x = x;    this.y = y;  } // Will replace the default constructor.}
复制代码


关于 record 类,有很多可讨论的话题。这是一个大的变更,在合适的地方使用它们,它们会非常有用。我在这里没有涵盖所有内容,但希望这能让你了解它们所提供的能力。

6:模式匹配

模式匹配是 Oracle 在与 Java 冗长语法的斗争中做出的另一个举措。模式匹配在 Java 14 和 Java 15 中预览过,并正式添加到 Java 16 中,它可以在 instanceof 条件得到满足后消除不必要的类型转换。例如,我们都很熟悉这样的代码:


if (o instanceof Car) {  System.out.println(((Car) o).getModel());}
复制代码


如果你想要访问 Car 的方法,必要要这么做。在第二行,o 是 Car 的实例,这是毫无疑问的,instanceof 已经确认了这一点。如果我们使用模式匹配,只要做一个小小的改变:


if (o instanceof Car c) {  System.out.println(c.getModel());}
复制代码


现在,所有的对象类型转换都由编译器完成。看起来改变很小,但它避免了很多样板代码。这也适用于条件分支,当你进入一个已经明确了对象类型的分支:


if (!(o instance of Car c)) {  System.out.println("This isn't a car at all!");} else {  System.out.println(c.getModel());}
复制代码


你甚至可以在 instanceof 那一行使用模式匹配:


public boolean isHonda(Object o) {  return o instanceof Car c && c.getModel().equals("Honda");}
复制代码


虽然模式匹配不像其他一些变更那么大,但还是简化了常用的代码。

Java 17 将继续演进

当然,Java 12 到 Java 17 并不是只推出了这些更新,这些只是我认为比较有趣的部分。用最新的 Java 版本来运行大型项目需要很大的勇气,如果是从 Java 8 迁移过来,则更需要勇气。


如果有人犹豫不决,是可以理解的。但是,即使你没有迁移计划,或者某个升级计划可能持续数年之久,跟上语言新特性的变化总归是件好事。我希望我分享的这些内容能够让它们更加深入人心,让阅读过这些内容的人都可以开始考虑如何使用它们!


Java 17 很特别——它是下一个长期支持版本,接过了 Java 11 的接力棒,并且很可能在未来几年内成为迁移最多的 Java 版本。即使你现在还没有做好准备,可以开始学习起来了,当你身处基于 Java 17 的项目当中,你已经是一名经验丰富的开发者!


作者简介:


Christopher BielakSaggezza(被 Infostretch 收购的一家公司)的 Java 开发人员,他对软件开发语言有浓厚的兴趣。他在银行和金融领域有 10 年的工作经验,倡导向更尖端的技术迈进。


原文链接


Six Features From Java 12 to 17 to Get Excited About!

2021-12-31 09:276697

评论 6 条评论

发布
用户头像
:有些版本还没开始用就被声明为过时了
2022-01-20 14:05
回复
用户头像
都怀疑未来 java 跟kotlin会不会基本一样
2022-01-12 21:48
回复
用户头像
全部是语法糖,这些东西在Java8中都可以实现,顶多省了点代码,如果仅仅是这些优化,那并不值得升17
2021-12-31 14:47
回复
有两个孵化中项目,新的外部函数调用,外部内存访问,支持simd矢量化的库。
2022-01-01 10:57
回复
变化小说不值得升,变化大说不敢升,😅
2022-01-21 19:36
回复
用户头像
感觉真是转眼间,十个版本过去了😂
2021-12-31 11:19
回复
没有更多了
发现更多内容

以财证道,终身成长

少油少糖八分饱

读书笔记 思维 搞钱 致富 有钱人

FuncGPT(慧函数)教你用Mybatis进行一对一查询映射处理

SoFlu软件机器人

融云:AI 机器人在社交软件中的花样存在

融云 RongCloud

AI 融云 社交软件 AIGC My AI

一文看懂:小程序游戏需要版号吗?

FN0

融云深度参与「新加坡 GTLC 大会」,连接亚太机遇、开拓国际市场

融云 RongCloud

通信 服务 融云 GTLC 东南亚

云服务之PaaS:PaaS怎么帮助企业走向云

高端章鱼哥

云计算 低代码 PaaS JNPF

我是如何使用Spring Retry减少1000 行代码

越长大越悲伤

Java spring retry spring-retry

ARTS 薪火重启之第二周

渣渣辉

电商店铺管理,为何需要华为云云耀云服务器L实例

YG科技

九科信息成功签约中交房地产集团有限公司RPA项目

九科Ninetech

一张图读懂TuGraph Analytics开源技术架构

TuGraphAnalytics

大数据 分布式 流计算 图计算 流图

走进大模型

统信软件

人工智能 深度学习 大模型

如何将数据从 InfluxDB 无缝接入到 TDengine 中?来看看

TDengine

tdengine Influxdb 时序数据库

加入DevRun软件开发流水线实战营,即刻开启你的职场竞争力之旅!

科技热闻

常用的国内外组态软件推荐

2D3D前端可视化开发

物联网 组态软件 工业组态软件 web组态软件 SCADA

首批通过!柏睿数据旗下数据库产品获强制性国标最高级别认证

新消费日报

知识管理工具和方法有哪些?分享15种

易成管理学

产品经理 PingCode wiki软件 知识库管理软件

C++头文件和std命名空间

芯动大师

软件测试|如何使用ChatGPT生成思维导图

霍格沃兹测试开发学社

Last Week in Milvus

Zilliz

非结构化数据 开源社区 Milvus Zilliz 向量数据库

什么是HTTP代理?HTTP代理的作用?HTTP代理怎么设置?

巨量HTTP

代理IP IP地址 http代理 socks5代理

图智能在反洗钱方向的应用实践丨Fabarta 技术专栏

Fabarta

图计算 图分析 反洗钱 图智能 智能风控

Kyligence Copilot 登陆海外,斩获 Product Hunt 日榜 TOP 2

Kyligence

指标平台 Kyligence Copilot 数据分成

cad设计绘图必备:AutoCAD 2024激活中文附补丁安装教程

mac大玩家j

Mac软件 CAD绘图 CAD设计 cad工具

唯一受邀参会通信服务商!融云出席数字经济头部盛会「中数大会」并发言

融云 RongCloud

人工智能 互联网 通信 数字 融云

k8s发布应用

tiandizhiguai

微服务 云原生 k8s

几款常用基于Web的组态编辑器

2D3D前端可视化开发

物联网 web组态 web组态软件 组态可视化 web组态编辑器

2023年科技趋势展望报告,这几个领域程序员可以恰饭

互联网工科生

人工智能 软件开发 麦肯锡

国内智慧工业的实践,在一首曙光《长歌行》中

脑极体

AI 算力 数智化 曙光

社交语聊平台运营,需要哪些资质?语聊APP原生开发和混合uniapp开发的利弊分析

山东布谷科技胡月

语音聊天系统软件开发 语音直播平台开发 语音聊天室开发 语音程序源码 社交直播APP开发

基于Vue3.0的优秀低代码项目

这我可不懂

Vue 低代码

从Java 12到Java 17那些激动人心的新特性_语言 & 开发_InfoQ精选文章