JDK 新版本中都有哪些新特性?

面试回答

JDK 8 推出了 Lambda 表达式、Stream、Optional、新的日期 API 等

JDK 9 中推出了模块化

JDK 10 中推出了本地变量类型推断

JDK 12 中增加了 switch 表达式

JDK 13 中增加了 text block

JDK 14 中增加了 Records

JDK 15 中增加了封闭类

JDK 17 中扩展了 switch 模式匹配

JDK 19 中增加了协程

知识扩展

Stream

Java 8引入了Stream API,它提供了一种简洁、灵活且功能强大的方式来处理集合数据。

Optional

Java 8引入了Optional类,它是一个用于处理可能为空(null)值的容器类。Optional提供了一种优雅的方式来避免空指针异常,并使代码更加健壮和可读。

创建Optional对象

  • Optional.empty():创建一个空的Optional对象。
  • Optional.of(value):将非空的值包装在Optional对象中,如果value为空,则抛出NullPointerException。
  • Optional.ofNullable(value):将值包装在Optional对象中,如果value为空,则创建一个空的Optional对象。

判断Optional对象是否包含值

  • isPresent():判断Optional对象是否包含非空值。
  • isEmpty()(Java 11+):判断Optional对象是否为空。

获取Optional对象中的值

  • get():获取Optional对象中的值,如果值为空,则抛出NoSuchElementException异常。
  • orElse(defaultValue):获取Optional对象中的值,如果值为空,则返回defaultValue作为默认值。
  • orElseGet(Supplier):获取Optional对象中的值,如果值为空,则通过Supplier提供的函数生成一个默认值。
  • orElseThrow(ExceptionSupplier):获取Optional对象中的值,如果值为空,则通过ExceptionSupplier提供的函数抛出自定义异常。

链式操作

  • map(Function):对Optional对象中的值进行映射转换。
  • flatMap(Function):对Optional对象中的值进行扁平化处理。
  • filter(Predicate):对Optional对象中的值进行过滤。
  • ifPresent(Consumer):如果Optional对象中的值非空,则执行给定的操作。

使用Optional可以更安全地处理可能为空的值,避免了繁琐的空指针检查和异常处理。它提供了一种优雅的方式来处理可能缺失的值,并鼓励编写更健壮、可读性更高的代码。

请注意,尽管Optional可以有效地处理空值,但在某些情况下,过度使用Optional可能会使代码变得复杂和冗长。因此,在使用Optional时应考虑适当的场景和平衡。

代码示例:


public class Main {public static void main(String[] args) {String name = "John";Optional<String> optionalName = Optional.ofNullable(name);// 检查Optional是否包含值if (optionalName.isPresent()) {System.out.println("Name is present: " + optionalName.get());} else {System.out.println("Name is absent");}// 使用orElse方法获取Optional的值,如果没有值则返回默认值String defaultName = optionalName.orElse("Default");System.out.println("Default name: " + defaultName);// 使用map方法对Optional的值进行转换Optional<String> upperCaseName = optionalName.map(String::toUpperCase);System.out.println("Upper case name: " + upperCaseName.orElse("No name"));// 使用flatMap方法对Optional的值进行扁平化处理Optional<String> flatMapExample = optionalName.flatMap(Main::getString);System.out.println("Flat map example: " + flatMapExample.orElse("No value"));}public static Optional<String> getString(String input) {if (input.isEmpty()) {return Optional.empty();}return Optional.of("Processed " + input);}}

输出如下:

Name is present: John
Default name: John
Upper case name: JOHN
Flat map example: Processed John

本地变量类型推断

在 Java 10 之前的版本中,我们想要定义局部变量时。我们需要在赋值的左侧提供显式类型,并在赋值的右边提供实现类型:

MyObject value=new MyObject();

在 Java 10 中,提供了本地变量类型推断的功能,可以通过 var 声明变量:

var value = new MyObject();

本地变量类型推断引入 “var”关键字,而不需要显式的规范变量的类型。

其实,所谓的本地变量类型推断,也是 java 10 提供给开发者的语法糖。

虽然我们在代码中使用 var 进行了定义,但是对于虚拟机来说他是不认识这个 var 的,在 java 文件编译成 class 文件的过程中,会进行解糖,使用变量真正的类型来替代 var。

Switch 表达式

在 JDK 12 中引入了 Switch 表达式作为预览特性。并在 Java 13 中修改了这个特性,引入了 yield 语句,用于返回值。

而在之后的 java 14 中,这一功能正式作为标准功能提供出来。

在以前,我们想要在 switch 中返回内容,还是比较麻烦的,一般语法如下:

    int i;switch (x) {case "1":i = 1;break;case "2":i = 2;break;default:i = x.length();break;}

在 JDK13 中使用一下语法:

int i = switch (x) {case "1" -> 1;case "2" -> 2;default -> {int len = x.length();yield len;}
};

或者:

    int i = switch (x) {case "1" :yield 1;case "2" :yield 2;default : {int len = x.length();yield len;}};

在这之后,switch 中就多了一个关键字用于跳出 switch 块了,那就是 yield,他用于返回一个值。

和 return 的区别在于: return 会直接跳出当前循环或者方法,而 yield 只会跳出当前 switch 块。

Text Blocks

Java 13 中提供了一个 Text Blocks 的预览特性,并且在 Java 14 中提供了第二个版本的预览。

text block,文本块,是一个多行字符串文字,它避免了对大多数转义序列的需要,以可预测的方式自动格式化字符串,并在需要时让开发人员控制格式。

我们以前从外部 copy 一段文本串到 Java 中,会被自动转义,如有一段以下字符串:

<html>
<body><p>hello,world</p>
</body>
</html>

将其复制到 Java 的字符串中,会展示成以下内容:

"<html>\n" +
"    <body>\n" +
"        <p>hello,world</p>\n" +
"    </body>\n" +
"</html>"

即被自动进行了转义,这样的字符串看起来不是很直观,在 JDK 13 中,就可以使用一下语法了:

"""
<html><body><p>hello,world</p></body>
</html>
"""

使用 """ 作为文本块的开始符和结束符,在其中就可以放置多行的字符串,不需要进行任何转义。看起来就十分清爽了。

如常见的 SQL 语句:

String query = """SELECT l.* FROM lin_log lWHERE l.is_deleted = 0ORDER BY l.create_time DESC""";

看起来就比较直观,清爽了。

Records

Java 14 中便包含了一个新特性:EP 359;Records

Records 的目标是扩展 Java 语言语法,Records 为声明类提供了一种紧凑的语法,用于创建一种类中是“字段,只是字段,除了字段什么都没有”的类。

通过对类做这样的声明,编译器可以通过自动创建所有方法并让所有字段参与 hashCode() 等方法。这是 JDK 14 中的一个预览特性。

使用 record 关键字可以定义一个记录:

public record Person(String firstName,String lastName) {
}
public static void main(String[] args) {Person person = new Person("Tango", "Chi");System.out.println(person.firstName());
}

record 解决了使用类作为数据包装器的一个常见问题。纯数据类从几行代码显著地简化为一行代码。

封闭类

在 Java 15 之前,Java 认为“代码重用”始终是一个终极目标,所以,一个类和接口都可以被任意的类实现或继承。

但是,在很多场景中,这样做是容易造成错误的,而且也不符合物理世界的真实规律。

例如,假设一个业务领域只适用于汽车和卡车,而不适用于摩托车。

在 Java 中创建 Vehicle 抽象类时,应该只允许 Car 和 Truck 类扩展它。

通过这种方式,我们希望确保在域内不会出现误用 Vehicle 抽象类的情况。

为了解决类似的问题,在 Java 15 中国引入了一个新的特性——密闭。

想要定义一个密闭接口,可以将 sealed 修饰符应用到接口的声明中。然后,permit 字句指定允许实现密闭接口的类:

public sealed interface Vehicle permits Car,Truck {
}

以上代码定义了一个密闭接口 Vehicle,它规定只能被 Car 和 Truck 两个类实现。

与接口类似,我们可以通过使用相同的 sealed 修饰符来定义密闭类:

public sealed abstract class Vehicle permits Car,Truck{
}

通过密闭特性,我们定义出来的 Vehicle 类只能被 Car 和 Truck 继承。

instanceof 模式匹配

instanceof 是 Java 中的一个关键字,我们在对类型做强制转换之前,会使用 instanceof 做一次判断,例如:

if (animal instanceof Dog){Dog dog=(Dog)animal;dog.run();
}else if (animal instanceof Cat){Cat cat=(Cat)animal;cat.run();
}

Java 14 带来了改进版的 instanceof 操作符,这意味着我们可以用更简洁的方式写出之前的代码例子:

if (animal instanceof Dog dog){dog.run();
}else if (animal instanceof Cat cat){cat.run();
}

我们都不难发现这种写法大大简化了代码,省略了显式强制类型转换的过程,可读性也大大提高了。

switch 模式匹配

基于 instanceof 模式匹配这个特性,我们可以使用如下方式来对对象 o 进行处理:

static String formatter(Object o) {String formatted = "unknow";if (o instanceof Integer i) {formatted = String.format("int %d", i);} else if (o instanceof Long l) {formatted = String.format("long %d", l);} else if (o instanceof Double d) {formatted = String.format("double %f", d);} else if (o instanceof String s) {formatted = String.format("String %s", s);}return formatted;
}

可以看到,这里使用了很多 if-else,其实,Java 中给我们提供了一个多路比较的工具,那就是 switch,而且从 Java 14 开始支持 switch 表达式,但 switch 的功能一直都是非常有限的。

在 Java 17 中,Java 的工程师们扩展了 switch 语句和表达式,使其可以适用于任何类型,并允许 case 标签中不仅带有变量,还能带有模式匹配。我们就可以更清楚、更可靠地重写上述代码,例如:

    static String formatter(Object o) {return switch (o) {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 -> o.toString();};}

可以看到,以上的 switch 处理的是一个 Object 类型,而且 case 中也不再是精确的值匹配,而是模式匹配了。

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

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

相关文章

探索未知世界:桌面端3D GIS引领地理信息新时代

近年来&#xff0c;桌面端的三维地理信息系统&#xff08;3D GIS&#xff09;在地理信息领域迎来了显著的发展&#xff0c;为我们带来了更深入、更丰富的地理空间认知和数据分析体验。从城市规划到环境保护&#xff0c;从资源管理到应急响应&#xff0c;桌面端的3D GIS正逐渐成…

Mysql定时备份事件

创建了一个名为backup_database的定时任务&#xff0c;每天自动在当前时间的后一天开始执行。备份数据库的代码使用mysqldump命令将数据库导出为sql文件保存在指定的备份目录中。 需要注意的是&#xff0c;上述代码中的用户名 (username)、密码 (password)、主机名 (hostname) …

Java程序设计——在一个给定的字符串中查找并解析姓名、出生日期、个人网站、身高和体重信息,并输出相应的结果

package ch4;public class FindMess {public static void main(String[] args) {String mess "姓名:张三 出生时间:1989.10.16。个人网站:http://www.zhang.com。身高:185 cm,体重:72 kg";int index (int)(mess.indexOf(":")); //mess调用indexOf(Stri…

如何解决跨域问题

跨域问题是指在浏览器中发起跨域请求时&#xff0c;由于浏览器的同源策略限制&#xff0c;导致请求被拒绝或无法正常发送和接收数据。同源策略要求两个页面具有相同的协议、域名和端口号&#xff0c;否则就会出现跨域问题。 为了解决跨域问题&#xff0c;可以采取以下方法之一…

git Update failed cannot lock ref

报错详情 解决方案 百度了很多方案&#xff0c;过滤出了有效方案 去该项目下的.git文件里找到报错文件&#xff0c;本例中即为&#xff1a;.git/refs/tags/pre-RELEASE-PRE-20230817-03 删除该文件&#xff0c;重新pull&#xff0c;pull成功问题解决

Java并发工具类

JDK并发包中常用并发工具类&#xff1a; CountDownLatch、CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段&#xff1b; Exchanger工具类则提供了在线程间交换数据的一种手段。 等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成…

Electron学习3 使用serialport操作串口

Electron学习3 使用serialport操作串口 一、准备工作二、 SerialPort 介绍1. 核心软件包(1) serialport(2) serialport/stream(3) serialport/bindings-cpp(4) serialport/binding-mock(5) serialport/bindings-interface 2. 解析器包3. 命令行工具 三、创建一个demo程序1. 创建…

NOI2015D. 荷马史诗

荷马史诗 题目描述 追逐影子的人&#xff0c;自己就是影子。 ——荷马 Allison 最近迷上了文学。她喜欢在一个慵懒的午后&#xff0c;细细地品上一杯卡布奇诺&#xff0c;静静地阅读她爱不释手的《荷马史诗》。但是由《奥德赛》和《伊利亚特》组成的鸿篇巨制《荷马史诗》实在是…

Dapper

介绍 dapper是一款轻量级的ORM Dapper 被称为 ORM 之王。 以下是 Dapper 的主要功能&#xff1a; 速度快&#xff0c;性能快。 更少的代码行。 对象映射器。 静态对象绑定。 动态对象绑定。 轻松处理 SQL 查询。 易于处理存储过程。 直接对 IDBConnection 类进行操作&#xf…

重注微电子产业,“三大齿轮”能否带起香港经济的“第三轮”

文 | 智能相对论 作者 | 佘凯文 众所周知&#xff0c;微电子产业早已成为现代科技领域的关键钥匙&#xff0c;谁能掌握微电子产业&#xff0c;谁就能拥有全球科技领域的话语权。 从上世纪开始&#xff0c;微电子产业曾经历过几次重大转移&#xff0c;如70年代从美国转向日本…

零拷贝技术详解

当涉及到网络编程和IO操作时&#xff0c;数据拷贝是一个常见的性能瓶颈。传统的数据拷贝过程中&#xff0c;数据需要从内核缓冲区复制到用户空间缓冲区&#xff0c;然后再从用户空间缓冲区复制到内核缓冲区&#xff0c;这个过程会耗费大量的CPU时间和内存带宽&#xff0c;降低系…

tensorRT安装

官方指导文档&#xff1a;Installation Guide :: NVIDIA Deep Learning TensorRT Documentation 适配很重要&#xff01;&#xff01;&#xff01;&#xff01; 需要cuda, cuDNN, tensorRT三者匹配。我的cuda11.3 所以对应的cuDNN和tensorRT下载的是如下版本&#xff1a; cud…

【业务功能篇77】微服务-OSS对象存储-上传下载图片

3. 图片管理 文件存储的几种方式 单体架构可以直接把图片存储在服务器中 但是在分布式环境下面直接存储在WEB服务器中的方式就不可取了&#xff0c;这时我们需要搭建独立的文件存储服务器。 3.1 开通阿里云服务 针对本系统中的相关的文件&#xff0c;图片&#xff0c;文本等…

docker 安装操作

1.安装docker服务&#xff0c;配置镜像加速器 安装软件包[rootbogon ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 设置yum源 [rootbogon ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 安装 […

python爬虫爬取中关村在线电脑以及参数数据

一. 内容简介 python爬虫爬取中关村在线电脑以及参数数据 二. 软件环境 2.1vsCode 2.2Anaconda version: conda 22.9.0 三.主要流程 3.1 代码 解析都在代码里面 # 接口分析 # 原始接口&#xff0c;后面几个数字就是占位的&#xff0c;每个位置代表着不同的标签 # http…

07-Numpy基础-伪随机数生成

numpy.random模块对Python内置的random进行了补充&#xff0c;增加了一些用于高效生成多种概率分布的样本值的函数。 例如&#xff0c;你可以用normal来得到一个标准正态分布的44样本数组&#xff1a; 而Python内置的random模块则只能一次生成一个样本值。从下面的测试结果中可…

Mybatis查询一条数据

上一篇我们介绍了在pom文件中引入mybatis依赖&#xff0c;配置了mybatis配置文件&#xff0c;通过读取配置文件创建了会话工厂&#xff0c;使用会话工厂创建会话获取连接对象读取到了数据库的基本信息。 如果您需要对上面的内容进行了解&#xff0c;可以参考Mybatis引入与使用…

Python爬虫(十五)_案例:使用bs4的爬虫

本章将从Python案例讲起&#xff1a;所使用bs4做一个简单的爬虫案例&#xff0c;更多内容请参考:Python学习指南 案例&#xff1a;使用BeautifulSoup的爬虫 我们已腾讯社招页面来做演示&#xff1a;http://hr.tencent.com/position.php?&start10#a 使用BeautifulSoup4解析…

Elasticsearch中的数据完全备份至另外的Elasticsearch

有两种方式实现&#xff1a; 1、快照和还原 2、导出和导入 一、快照和还原 1、在源Elasticsearch集群上创建快照存储库 PUT _snapshot/my_backup {"type": "fs","settings": {"location": "/path/to/backup/directory"}…

【前端】vue3 接入antdv表单校验

1/&#x1f355;背景 1、表单校验是非常常见的需求&#xff0c;能够有效的拦截大部分的错误数据&#xff0c;提升效率。 2、快速的给使用者提示和反馈&#xff0c;用户体验感非常好。 3、成熟的表单校验框架&#xff0c;开发效率高&#xff0c;bug少。 最近使用的是vue3antdv的…