Java 19和IntelliJ IDEA,如何和谐共生?

news2024/10/2 6:39:49

Java仍然是目前比较流行的编程语言,它更短的发布节奏让开发者每六个月左右就可以试用新的语言或平台功能,IntelliJ IDEA帮助我们更流畅地发现和使用这些新功能。

IntelliJ IDEA v2022.3正式版下载(Q技术交流:786598704)

在本文中,我们将只介绍Java 19的语言功能:记录模式和switch模式匹配(第三版预览),特意避开其他Java 19功能,例如预览API虚拟线程。IntelliJ IDEA支持虚拟线程的基本语法高亮显示,官方团队正努力在调试器和分析器中添加对虚拟线程的支持。

记录模式简化了对记录组件的访问,比较记录模式和记录析构 – 当实例与记录结构匹配时,将记录组件的值提取到一组变量,它与 switch 和密封类的模式匹配等其他语言功能结合使用时,效果十分惊人。

switch 的模式匹配将模式添加到 switch 语句和 switch 表达式中的 case 标签,可以与 switch 一起使用的选择器表达式的类型扩展为任意引用值。 另外case 标签不再限于常量值,它还有助于将 if-else 语句链替换为 switch,提高代码可读性。 在这篇博文中,我们将介绍 switch 模式匹配第三版预览中引入的更改。

先从为使用 Java 19 功能对IntelliJ IDEA 进行配置开始。

IntelliJ IDEA 配置

IntelliJ IDEA 2022.3 中提供了对 Java 19 的支持,未来的 IntelliJ IDEA 版本将提供更多支持。 要通过 Java 19 使用 switch 的模式匹配,先转到 Project Settings | Project(项目设置 | 项目),将 Project SDK(项目 SDK)设为 19,然后将项目语言级别设置为 19 (Preview) – Record patterns, pattern matching for switch (third preview)

开发者可以使用系统上已经下载的任意版本JDK,也可以点击 Edit(编辑),然后选择 Add SDK >(添加 SDK)、Download JDK…(下载 JDK…)来下载其他版本,可以从供应商列表中选择要下载的 JDK 版本。

在 Modules(模块)选项卡上,确保为模块选择相同的语言级别 – 19 (Preview) – Record patterns, pattern matching for switch (third preview)

选择此选项后,可能会出现以下弹出窗口,通知您 IntelliJ IDEA 可能会在后续版本中停止对 Java 预览语言功能的支持。 因为预览功能(暂且)不是永久性的,并且它可能在未来的 Java 版本中发生变化(甚至被移除)。

为什么需要记录模式?

数据是大多数应用程序的核心,通常开发者使用的应用程序可以查找数据,或者以帮助开发者做出决策的方式处理数据。当然如果应用程序无法存储、检索或处理其数据,这是不可行的。

在最近的一个 Java 版本(第 16 版)中,记录被添加到 Java 语言中,让开发者可以轻松处理数据。 记录大幅简化了对不可变数据建模的方式,它们充当数据的透明载体或包装器,只需使用一行代码,就可以定义一条记录及其组件。

例如,以下单行代码会创建一条新记录 Person,后者可以存储其组件 name 的字符串值和 age 的整数值:

record Person (String name, int age) { }

记录让开发者不必些示例代码,记录会隐式生成其构造函数的默认实现、其组件的访问器方法,以及 toString、equals 和 hashCode 等效用函数方法。 使用记录作为数据的包装器时,您很可能需要将其展开来访问其组件。 例如,对于记录 Person 的实例,可能想要检查其年龄组件以确定它所代表的人是否有资格投票,isEligibleToVote 这样的方法可以完成这个操作:

boolean isEligibleToVote(Object obj) {
if (obj instanceof Person person) {
return person.age() >= 18;
}
return false;
}

前面的示例使用了 instanceof 的模式匹配,它声明了一个模式变量 person,因此您不需要创建局部变量来将 obj 转换为 Person。

记录模式更进一步。 它不仅将实例与记录类型 Person 比较,还声明了记录组件的变量,因此无需定义局部变量或使用模式变量来访问记录的组件,这都要归功于编译器知道记录组件的确切数量和类型。

使用记录模式重写前面的方法,将记录类型与 instanceof 运算符配合使用或在 switch case 标签中使用时,IntelliJ IDEA可以检测到它并建议使用记录模式:

这是修改后的代码:

boolean isEligibleToVote(Object obj) {
if (obj instanceof Person(String name, int age)) {
return age >= 18;
}
return false;
}

在前面的代码中,记录模式 Person(String name, int age) 似乎允许使用变量 age 代替 person.age()。 然而继续阅读,将了解记录模式能够简化代码的意图,还有助于创建简洁的数据处理代码。

命名记录模式

记录模式后面可以跟随一个记录模式变量,这种情况下,记录模式被称为命名记录模式(虽然没有得到确认,但 Java 20 的记录模式的第二版预览可能会放弃对命名记录模式的支持)。

记录模式还可以为其组件定义模式变量,用命名记录模式并尝试使用记录模式变量访问其组件时,IntelliJ IDEA 会提示您为其组件使用模式变量,将看到此类代码以黄色背景高亮显示,可以使用 Alt+Enter 查看建议,并接受修改代码的建议:

记录模式和 null

我们回顾一下上一部分中的 isEligibleToVote 方法示例,如果将 null 值传递给以下方法会发生什么:

boolean isEligibleToVote(Object obj) {
if (obj instanceof Person(String name, int age)) {
return age >= 18;
}
return false;
}

由于 null 不是记录模式 Person(String name, int age) 的实例,instanceof 运算符返回 false,并且模式变量 name 和 age 未初始化。这很方便,因为记录模式会处理null,开发者不需要定义非 null 检查。

但是如果组件 name 的值为 null,则模式将被匹配。

嵌套记录模式 – 简洁的代码和明确的意图

将另一条记录定义为其组件的记录相当常见,例如:

record Name (String fName, String lName) { }
record PhoneNumber(String areaCode, String number) { }
record Country (String countryCode, String countryName) { }
record Passenger (Name name,
PhoneNumber phoneNumber,
Country from,
Country destination) { }

如果没有可以检查 null 组件值的记录模式,您将需要几个 null 检查运算来处理记录 Passenger 的 fName 和 countryCode 的组件值,如下所示:

boolean checkFirstNameAndCountryCode (Object obj) {
if (obj != null) {
if (obj instanceof Passenger passenger) {
Name name = null;
Country destination = null;

if (passenger.name() != null) {
name = passenger.name();

if (passenger.destination() != null) {
destination = passenger.destination();

String fName = name.fName();
String countryCode = destination.countryCode();

if (fName != null && countryCode != null) {
return fName.startsWith("Simo") &&
countryCode.equals("PRG");
}
}
}
}
}
return false;
}

同样的行为可以通过嵌套记录模式实现,这也将使代码的意图更加清晰。 如果记录组件 name 和 destination 为 null,instanceof 检查将失败:

boolean checkFirstNameAndCountryCodeAgain (Object obj) {
if (obj instanceof Passenger(Name (String fName, String lName),
PhoneNumber phoneNumber,
Country from,
Country (String countryCode, String countryName) )) {

if (fName != null && countryCode != null) {
return fName.startsWith("Simo") && countryCode.equals("PRG");
}
}
return false;
}

如前面的示例代码所示,开发者可以有选择地添加主记录组件的记录模式。 例如前面的示例没有为组件 from 使用记录模式,但它为主记录 Passenger 的记录组件目标使用记录模式。 简而言之,定义记录模式时,开发者可以控制要提取到模式变量的详细信息,这一功能非常适合数据处理密集型应用程序。

将var与记录模式一起使用

来回顾一下前面示例中的方法 checkFirstNameAndCountryCodeAgain,并将一些模式变量的类型定义为 var:

boolean checkFirstNameAndCountryCodeAgain (Object obj) {
if (obj instanceof Passenger(Name (String fName, var lName),
var phoneNumber,
Country from,
Country (var countryCode, String countryName) )) {

if (fName != null && countryCode != null) {
return fName.startsWith("Simo") && countryCode.equals("PRG");
}
}
return false;
}

开发者可以将部分或全部模式变量的类型定义为var,如果您好奇它们的类型,IntelliJ IDEA 可以显示:

记录模式和泛型

如果记录是泛型,则其记录模式必须使用泛型类型。 例如假设类 WristWatch 和泛型记录 Gift 的定义如下:

class WristWatch {}
record Gift<T>(T t) {}

开发者可以使用以下方法解开记录 Gift 的实例,可以使用 var 或 WristWatch 作为模式变量 watch 的类型:

void unwrap(Gift<WristWatch> obj) {
if (obj instanceof Gift<WristWatch> (var watch)) {
System.out.println(watch);
}
}

但是,以下代码将不起作用:

static void cannotUnwap(Gift<object> obj) {
if (obj instanceof Gift(var s)) { // won’t compile
//..
}
}

下一部分使用记录模式和 switch 表达式创建强大的递归方法。

记录模式、switch 表达式和密封类

结合记录模式、switch 表达式和密封类,开发者可以创建功能强大、简洁且富有表现力的代码来处理数据。 这是密封接口 TwoDimensional 的示例,它由记录 Point、Line、Triangle 和 Square 实现:

sealed interface TwoDimensional {}
record Point (int x, int y) implements TwoDimensional { }
record Line ( Point start,
Point end) implements TwoDimensional { }
record Triangle( Point pointA,
Point pointB,
Point PointC) implements TwoDimensional { }
record Square ( Point pointA,
Point pointB,
Point PointC,
Point pointD) implements TwoDimensional { }

下面的方法定义了一个递归方法进程,它使用 switch 构造返回二维图形(如 Line、Triangle 或 Square)中所有点的 x 和 y 坐标之和:

static int process(TwoDimensional twoDim) {
return switch (twoDim) {
case Point(int x, int y) -> x + y;
case Line(Point a, Point b) -> process(a) + process(b);
case Triangle(Point a, Point b, Point c) ->
process(a) + process(b) + process(c);
case Square(Point a, Point b, Point c, Point d) ->
process(a) + process(b) + process(c) + process(d);
};
}

IntelliJ IDEA 还会在此方法的间距中显示递归调用图标:

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

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

相关文章

小樽C++ 多章⑧ (叁) 指针与字符串、(肆) 函数与指针

目录 叁、函数与字符串 肆、函数与指针 4.1 指针作为函数参数 4.2 函数返回指针 4.3 函数指针与函数指针数组 4.4 结构体指针 ​​​​​​​​​​​​​​小樽C 多章⑧ (壹) 指针变量https://blog.csdn.net/weixin_44775255/article/details/129031168 小樽C 多章⑧ …

数据可视化的正确逻辑和关键点

由于移动互联网和手机的普及发展&#xff0c;截至2022年6月&#xff0c;我国短视频的用户规模达9.62亿&#xff1b;即时通信用户规模达10.27亿&#xff1b;网络新闻用户规模达7.88亿&#xff1b;网络直播用户规模达7.16亿......这些数据都意味着互联网已经涉及我们的方方面面&a…

Java并发编程与API详解

文章目录前言操作系统——进程和线程进程进程组成进程状态进程控制进程创建进程终止进程阻塞和唤醒进程通信线程线程组成线程状态线程控制线程的实现方式用户线程内核线程混合方式CPU调度调度的层次调度的实现调度器调度的时机、切换与过程进程调度的方式闲逛进程两种线程的调度…

合作伙伴管理软件如何帮助简化您的业务流程?

随着合作伙伴数量的增加&#xff0c;企业需要处理更多的信息和数据&#xff0c;并在更多的项目上进行协调和管理。这会增加企业的复杂性和工作量&#xff0c;使管理变得更加困难。同时&#xff0c;随着合作伙伴项目数量的增加&#xff0c;企业需要与更多的合作伙伴进行协调和沟…

Echarts 水波图实现

开发的项目中需要实现这样一个水波图&#xff0c;例如下图在echarts官网中找了很久没找到&#xff0c;后面是在Echarts社区中找到的&#xff0c;实现了大部分的样式&#xff0c;但是还有一些数据的展示没有实现。水波图的数值展示是默认整数百分比&#xff0c;我的需求是需要保…

【算法数据结构体系篇class14、15】:并查集

一、并查集1)有若干个样本a、b、c、d…类型假设是V2)在并查集中一开始认为每个样本都在单独的集合里3)用户可以在任何时候调用如下两个方法&#xff1a;boolean isSameSet(V x, V y) : 查询样本x和样本y是否属于一个集合void union(Vx, V y) : 把x和y各自所在集合的所有样本合并…

带你玩转modbusTCP通信

modbus TCP Modbus TCP是一种基于TCP/IP协议的Modbus通信协议&#xff0c;它是Modbus协议的一种变体&#xff0c;用于在以太网上进行通信。Modbus TCP协议是一种开放的通信协议&#xff0c;它支持多种编程语言和操作系统&#xff0c;并且可以在不同的硬件和软件平台上进行通信…

从0开始学python -49

Python MySQL - mysql-connector 驱动 -2 插入数据 插入数据使用 “INSERT INTO” 语句&#xff1a; demo_mysql_test.py: 向 sites 表插入一条记录。 import mysql.connectormydb mysql.connector.connect(host"localhost",user"root",passwd"…

液氮恒温器概述

恒温器是直接或间接控制一个或多个热源和冷源来维持所要求的温度的一种装置。 恒温器要实现这种功能&#xff0c;就必须具有一个敏感元件和一个转换器&#xff0c;敏感元件量度出温度的变化&#xff0c;并对转换器产生所需的作用。转换器把来自敏感元件的作用转换成对改变温度…

创建型设计模式(C++)

文章目录1.简单工厂模式&静态工厂模式2.工厂方法模式3.抽象工厂模式4.原型模式5.单例模式a.饿汉式b.懒汉式6.建造者模式&#xff08;生成器模式&#xff09;创建型模式提供了创建对象的机制&#xff0c;旨在提升已有代码的灵活性和可复用性。 部分插图来自&#xff1a; ht…

20230308 Apdl lsdyna两杆撞击案例学习笔记

本次模拟使用的是ANSYS 16.0 一、设置Element type 首先打开APDL界面 添加element type 在LS-DYNA Explicit选择条件下,选择3D solid 164 二、设置材料类型 选择material models 选择Elastic-Isotropic-输入 Density:密度 EX:杨氏模量 NUXY:泊松比 三、几何模型建…

小应用记账本-第2章-数据库设计

小应用记账本-第2章-数据库设计 在上一章《小应用记账本-第1章-需求分析》已经罗列了我们需要的功能&#xff0c;因为很简单&#xff0c;所以这一章就来设计数据库吧。 Account表&#xff1a;账户表 字段名类型说明取值idint账户idaccount_namevarchar账户名称remaining_sumd…

【目标检测论文解读复现NO.33】改进YOLOv5的新能源电池集流盘缺陷检测方法

前言此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c;…

python+opencv生成较真实的车牌号码图片

本文参考github代码&#xff1a;https://github.com/loveandhope/license-plate-generator 效果&#xff1a; 一、代码目录结构&#xff1a; font目录下存放车牌中文、字符的ttf字体 images目录下存放蓝色底牌、新能源绿色底牌、污渍&#xff08;噪声&#xff09;的图片 完整…

嵌入式物联网毕业设计选题智能图像识别项目-stm32mp157 linux开发板

stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器&#xff0c;集成2个Cortex-A7核和1个Cortex-M4 核&#xff0c;A7核上可以跑Linux操作系统&#xff0c;M4核上可以跑FreeRT…

ControlNet-有条件图文生成论文阅读

文章目录摘要算法&#xff1a;ControlNetControlNet in Image Diffusion ModelTrainingImproved Training实验Canny edgesHough linesHuman scribblesHED boundary mapOpenpifpaf poseOpenposeADE20K segmentation mapCOCO-Stuff segmentation mapDIODE normal mapDepth-to-Ima…

蓝桥冲刺31天之第六天

今天是摆子的一天&#xff0c;明天我要肝一整天的第四题&#xff01;&#xff01;&#xff01; PS&#xff1a;一个普通的排序罢了 import java.io.*; import java.util.Arrays; import java.util.Scanner;/*** ClassName 考勤刷卡* Description TODO* Author 小怂很怂* Date 2…

DataX与DB2导入导出案例

DataX与DB2导入导出案例 文章目录DataX与DB2导入导出案例0. 写在前面1. DB2介绍2. DB2数据库对象关系3. 安装前的准备3.1 安装依赖3.2 修改配置文件 sysctl.conf3.3 修改配置文件 limits.conf4. 安装4.1 预检查4.2 添加组和用户4.3 创建实例4.4 创建实例库、开启服务4.5 连接5.…

在CentOS7上静默安装Oracle19c

1.下载Oracle 官方安装包下载路径&#xff08;需要登录Oracle账号&#xff09;&#xff1a; https://www.oracle.com/database/technologies/oracle-database-software-downloads.html#19c 可选择windows/Linux平台对应的安装包&#xff0c;我选择Linux x86-64、ZIP包下载&…

分析linux内核移植中vmlinux可执行文件是如何生成的?以及 uImage/zImage/Image/vmlinx之间关系

一&#xff1a;分析linux内核移植中vmlinux可执行文件是如何生成的&#xff1f; 1&#xff1a;进入内核源码顶层目录下打开Makefile文件&#xff0c;搜索vmlinux 这里构建vmlinux的命令使用了makefile的内置函数call。这是一个比较特殊的内置函数&#xff0c;make使用它来引用…