Java 14 新特性解析与代码示例

Java 14 新特性解析与代码示例

文章目录

  • Java 14 新特性解析与代码示例
    • 1. 开关表达式(Switch Expressions)
    • 2. 记录类型(Records)
    • 3. 文本块(Text Blocks)
    • 4. instanceof的模式匹配(Pattern Matching for instanceof)
    • 5. 更有帮助的NullPointerException(Helpful NullPointerExceptions)
    • 6. 其他特性
    • 7. 版本演进与选择建议
    • 8. 结语

Java 14(2020年3月发布)为Java开发者带来了多项新特性和改进,旨在提升代码的可读性、简洁性和调试效率。本文将深入探讨Java 14的五大核心特性:开关表达式(Switch Expressions)、记录类型(Records)、文本块(Text Blocks)、instanceof的模式匹配(Pattern Matching for instanceof)以及更有帮助的NullPointerException(Helpful NullPointerExceptions)。每个特性都将通过详细的解释和完整的代码示例进行说明,并与旧方法进行对比,以展示其优势。以下是关键要点和详细内容。

关键要点

  • 开关表达式(Switch Expressions):Java 14将开关表达式标准化,允许switch语句作为表达式返回一个值,消除了break语句的需求,使代码更简洁、更安全。
  • 记录类型(Records):作为预览特性,Records提供了一种简洁的方式来定义不可变数据类,自动生成构造器、访问器和常见方法,减少了样板代码。
  • 文本块(Text Blocks):作为预览特性,文本块简化了多行字符串的定义,消除了字符串拼接和转义字符的麻烦,特别适合HTML、JSON等场景。
  • instanceof的模式匹配:作为预览特性,允许在类型检查时直接声明变量并自动转换类型,减少了显式类型转换的冗余代码。
  • 更有帮助的NullPointerException:通过更详细的异常消息,明确指出哪个变量为null,显著提升了调试效率。

在这里插入图片描述

1. 开关表达式(Switch Expressions)

开关表达式(JEP 361)是Java 14中标准化的特性,最初在Java 12和13中作为预览特性引入。它通过以下方式改进了传统switch语句:

  • 新语法:使用->代替:,消除了break语句的需要。
  • 多值case:支持在单个case中指定多个值(如case 1, 3, 5)。
  • 返回值:switch可以作为表达式直接返回值,使用yield关键字处理复杂逻辑。
  • 强制完整性:对于非枚举类型,switch表达式必须覆盖所有可能的分支。

传统switch语句的问题

  • 容易发生"穿透",如果遗漏break,会导致意外执行后续case。
  • 不能直接返回值,需额外定义变量。

代码示例

public class SwitchExpressionDemo {public static void main(String[] args) {int month = 2; // February// 传统switch语句 - 需要break和额外变量int days;switch (month) {case 1:case 3:case 5:case 7:case 8:case 10:case 12:days = 31;break;case 4:case 6:case 9:case 11:days = 30;break;case 2:days = 28; // 非闰年break;default:days = -1; // 无效月份break;}System.out.println("传统方式 - Days in month: " + days);// 开关表达式 - 简洁安全int daysExpr = switch (month) {case 1, 3, 5, 7, 8, 10, 12 -> 31; // 多值casecase 4, 6, 9, 11 -> 30;case 2 -> 28; // 非闰年default -> -1; // 无效月份};System.out.println("开关表达式 - Days in month: " + daysExpr);// 使用yield处理复杂逻辑String day = "Monday";String result = switch (day) {case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> {System.out.println("工作日!");yield "Weekday"; // yield返回值}case "Saturday", "Sunday" -> {System.out.println("周末!");yield "Weekend";}default -> "Unknown";};System.out.println("Result: " + result);}
}

优点

  • 减少了样板代码,提高了可读性
  • 消除了穿透问题,增强了代码安全性
  • 支持在表达式中直接使用switch,增加了灵活性

注意事项

  • 开关表达式必须是完整的,编译器会检查是否覆盖所有可能值
  • 不能混用:->语法
  • yield仅在switch块内返回值,不同于return

2. 记录类型(Records)

记录类型(JEP 359)是Java 14的预览特性,旨在为不可变数据类提供简洁的定义方式。Records自动生成以下内容:

  • 不可变字段(final)
  • 规范构造器(Canonical Constructor)
  • 访问器方法(Accessor Methods)
  • equals()hashCode()toString()方法

注意:Records是Java 14的预览特性,编译和运行时需添加参数:

  • 编译:javac --enable-preview --release 14
  • 运行:java --enable-preview

传统类的问题

  • 需要手动编写大量样板代码,如构造器、访问器和方法
  • 容易出错,尤其是在实现equals()hashCode()

代码示例

public class RecordDemo {// 传统类 - 需要大量样板代码public static class Point {private final int x;private final int y;public Point(int x, int y) {this.x = x;this.y = y;}public int getX() { return x; }public int getY() { return y; }@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Point point = (Point) o;return x == point.x && y == point.y;}@Overridepublic int hashCode() {return Objects.hash(x, y);}@Overridepublic String toString() {return "Point{x=" + x + ", y=" + y + "}";}}// Record - 一行定义等效功能public record PointRecord(int x, int y) {// 紧凑构造器 - 可添加验证逻辑public PointRecord {if (x < 0 || y < 0) {throw new IllegalArgumentException("坐标不能为负数");}}// 添加自定义方法public double distanceTo(PointRecord other) {return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));}// 添加转换方法public PointRecord withX(int newX) {return new PointRecord(newX, this.y);}}public static void main(String[] args) {Point point = new Point(3, 4);System.out.println("传统类: " + point);PointRecord record = new PointRecord(3, 4);System.out.println("Record: " + record);System.out.println("Distance to (0,0): " + record.distanceTo(new PointRecord(0, 0)));// 使用转换方法PointRecord moved = record.withX(5);System.out.println("Moved point: " + moved);}
}

优点

  • 显著减少样板代码
  • 明确表达不可变数据类的意图
  • 支持自定义方法和构造器,增加灵活性

注意事项

  • Records是预览特性(Java 16中转正)
  • Records不可继承其他类,但可实现接口
  • 适合数据传输对象(DTO)等场景,不适合需要可变性的类

3. 文本块(Text Blocks)

文本块(JEP 368)是Java 14的预览特性,旨在简化多行字符串的定义。它们使用三引号(""")定义,保留原始格式,消除了字符串拼接和转义字符的需要。

注意:文本块是预览特性,编译和运行参数同Records。该特性在Java 15中转正。

传统字符串的问题

  • 需要使用\n+进行拼接,代码复杂且不易读
  • 嵌入HTML、JSON等内容时,转义字符(如\")增加复杂性

代码示例

public class TextBlockDemo {public static void main(String[] args) {// 传统字符串 - 需要拼接和转义String htmlTraditional = "<html>\n" +"<body>\n" +"<h1>Hello, World!</h1>\n" +"</body>\n" +"</html>";System.out.println("传统字符串:\n" + htmlTraditional);// 文本块 - 保持原始格式String htmlTextBlock = """<html><body><h1>Hello, World!</h1></body></html>""";System.out.println("文本块:\n" + htmlTextBlock);// 使用转义字符 - 抑制换行String noNewline = """Line one \Line two""";System.out.println("无换行:\n" + noNewline);  // 输出: Line one Line two// 使用转义字符 - 显式插入空格String preserveSpace = """one    \stwo    \s""";System.out.println("保留空格:\n" + preserveSpace);// JSON示例String json = """{"name": "张三","age": 30,"email": "zhangsan@example.com"}""";System.out.println("JSON文本块:\n" + json);}
}

缩进规则
文本块以结束符"""的位置为基准,自动去除每行前的公共空白:

String text = """HelloWorld!"""; 
// 实际存储:"Hello\n  World!"

新转义字符

  • \:抑制换行
  • \s:显式插入空格(避免行尾空格被忽略)

优点

  • 提高多行字符串的可读性
  • 减少转义字符的使用
  • 适合嵌入复杂文本格式

注意事项

  • 避免在复杂表达式中内联使用文本块
  • 注意缩进规则,避免意外空白

4. instanceof的模式匹配(Pattern Matching for instanceof)

instanceof的模式匹配(JEP 305)是Java 14的预览特性,允许在类型检查时直接声明变量并自动转换类型,简化了代码。

注意:此特性是预览特性(Java 16中转正),编译运行参数同前。

传统instanceof的问题

  • 需要显式类型转换,增加代码冗余
  • 容易出错,尤其是在复杂类型层次结构中

代码示例

public class PatternMatchingDemo {// 使用继承层次结构abstract static class Animal {}static class Cat extends Animal {void meow() { System.out.println("喵喵!"); }}static class Dog extends Animal {void woof() { System.out.println("汪汪!"); }}public static void main(String[] args) {Animal animal = new Cat();// 传统instanceof - 需要显式转换if (animal instanceof Cat) {Cat cat = (Cat) animal;cat.meow();} else if (animal instanceof Dog) {Dog dog = (Dog) animal;dog.woof();}// 模式匹配 - 合并检查和转换if (animal instanceof Cat cat) {cat.meow(); // 直接使用cat变量} else if (animal instanceof Dog dog) {dog.woof();}// 在表达式中使用String sound = (animal instanceof Cat cat) ? "喵喵" : (animal instanceof Dog dog) ? "汪汪" : "未知";System.out.println("动物叫声: " + sound);}
}

优点

  • 合并类型检查和转换,减少代码量
  • 提高代码可读性和安全性
  • 模式变量仅在匹配时有效,限制了作用域

注意事项

  • 模式变量是final的,不能重新赋值
  • 在复杂条件表达式中使用需谨慎

5. 更有帮助的NullPointerException(Helpful NullPointerExceptions)

Helpful NullPointerExceptions(JEP 358)是Java 14的标准特性,通过提供更详细的异常消息,帮助开发者快速定位null变量。

传统NPE的问题

  • 仅提供行号,难以确定具体哪个变量为null
  • 在复杂方法链中,调试耗时

实现机制:JVM在类文件中记录局部变量表(LocalVariableTable)信息,使异常能定位具体变量。

代码示例

public class HelpfulNPEDemo {static class PersonalDetails {String getEmailAddress() { return null; }}static class Employee {PersonalDetails getPersonalDetails() { return null; }}public static void main(String[] args) {Employee employee = null;// 传统NPE - 只有行号信息try {String emailAddress = employee.getPersonalDetails().getEmailAddress().toLowerCase();} catch (NullPointerException e) {System.out.println("传统NPE信息:");e.printStackTrace();}// 更好的实践:使用Objects.requireNonNulltry {String email = Objects.requireNonNull(employee, "employee不能为空").getPersonalDetails().getEmailAddress();} catch (NullPointerException e) {System.out.println("\n使用非空校验后的异常:");e.printStackTrace();}}
}

输出对比

  • 传统NPE(Java 13及之前):

    传统NPE信息:
    java.lang.NullPointerExceptionat HelpfulNPEDemo.main(HelpfulNPEDemo.java:14)
    
  • Helpful NPE(Java 14+):

    java.lang.NullPointerException: Cannot invoke "HelpfulNPEDemo$Employee.getPersonalDetails()" because "employee" is nullat HelpfulNPEDemo.main(HelpfulNPEDemo.java:10)
    

优点

  • 明确指出null变量,简化调试
  • 默认启用,无需额外配置
  • 仅对JVM抛出的NPE有效,自定义NPE不受影响

注意事项

  • 在极端性能敏感场景可考虑禁用(不推荐)
  • 结合Objects.requireNonNull使用效果更佳

6. 其他特性

Java 14还包括以下特性:

  • Foreign Memory Access API(JEP 370):孵化特性,提供安全高效的外部内存访问
  • Packaging Tool(JEP 343):孵化特性,用于创建原生安装包
  • ZGC on Windows and macOS(JEP 364, 365):实验特性,将低延迟垃圾收集器扩展到Windows和macOS
  • NUMA-Aware Memory Allocation for G1(JEP 345):优化G1垃圾收集器在NUMA架构上的性能
  • JFR Event Streaming(JEP 349):支持实时监控JDK Flight Recorder数据

由于篇幅限制,这些特性将在后续文章中详细探讨。

7. 版本演进与选择建议

  • 预览特性转正时间

    • Java 15:文本块转正
    • Java 16:Records和instanceof模式匹配转正
  • 版本选择建议

    对于新项目,推荐采用Java 17(LTS)作为基线版本,它可以获得所有转正特性,同时享受长期支持。生产环境中使用预览特性需谨慎评估。

8. 结语

Java 14通过引入开关表达式、记录类型、文本块、instanceof的模式匹配和更有帮助的NullPointerException等特性,显著提升了代码的简洁性、可读性和调试效率。这些特性是Java语言现代化的重要里程碑,帮助开发者更高效地编写高质量代码。

参考资料

  • Oracle Java 14 Release Notes
  • OpenJDK JEP Index
  • Happy Coders - Java Records
  • Baeldung - Java 14 New Features
  • Happy Coders - Java Text Blocks
  • Pattern Matching for instanceof
  • Helpful NullPointerExceptions

希望本文能为您提供深入的见解和实用的代码示例!如果您有任何问题或建议,欢迎留言讨论。

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

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

相关文章

在虚拟机ubuntu上修改framebuffer桌面不能显示图像

目录 一、测试程序 二、排查原因 三、为什么 Xorg 会导致程序无法工作&#xff1f; 一、测试程序 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #in…

语言模型的评估指标整理

语言模型&#xff08;Language Models&#xff09;是自然语言处理&#xff08;NLP&#xff09;的核心组件&#xff0c;广泛应用于机器翻译、文本生成、对话系统等领域。随着模型复杂度的提升&#xff0c;如何科学、系统地评估模型性能变得至关重要。评估指标不仅帮助我们理解模…

【开发技术】.Net中配置Serilog日志分级记录

目录 一、目的 二、解决方案 2.1 下载serilog包 2.2 Serilog配置 2.2.1 使用多个File sink配置不同的最小日志级别 2.2.2 使用Filter条件分流到不同文件 三、使用建议 四、文章总结 一、目的 在日常开发中&#xff0c;需要根据不同的场景去记录日志&#xff0c;根据实际…

聊聊如何判断发现的缺陷属于前后端

目录 一、观察缺陷现象 二、检查网络请求&#xff08;核心方法&#xff09; 三、模拟请求验证后端 四、查看日志 五、数据流分析 六、判断前后端缺陷方法 判断发现的缺陷是前后端&#xff0c;可以通过观察缺陷现象&#xff0c;检查网络请求&#xff0c;查看后端日志&…

Python3与MySQL的PyMySQL连接与应用

Python3与MySQL的PyMySQL连接与应用 引言 随着互联网技术的飞速发展,数据库在各个领域的应用日益广泛。MySQL作为一种开源的关系型数据库管理系统,因其稳定性和高效性,被广泛应用于各种场景。Python作为一种高级编程语言,以其简洁、易读、易学等特点,受到了广大开发者的…

智慧城市SaaS平台|市政公用管理系统

【道路监测运维系统】1.数据可视化a) 实时监控支持对道路监测数据进行分析评估&#xff0c;为道路养护、交通管理、环境保护等提供数据支撑2.道路基础设施监测支持对道路基础设施的运行状态进行实时监测&#xff0c;包括路面状况3.交通流量监测支持对道路交通流量进行实时监测&…

Maven 配置阿里云镜像加速

Maven 配置阿里云镜像加速&#xff1a; 完整配置步骤&#xff08;Windows 系统&#xff09; 1. 找到 Maven 的 settings.xml 文件 全局配置&#xff1a;D:\software\apache-maven-3.9.11\conf\settings.xml用户配置&#xff1a;C:\Users\Admin\.m2\settings.xml&#xff08;推荐…

去除视频字幕 3 : 继续研究 IOPaint,记录几个问题

1. 为什么单独运行&#xff0c;效果很好&#xff0c;批量运行&#xff0c;效果很差。 1. 我运行 iopaint start --modellama --devicecuda --port8080在浏览器中单独选择图片&#xff0c;涂选区域&#xff0c;然后处理&#xff0c;此时的效果非常好。2. 但是我进行 iopaint ru…

【深度之眼机器学习笔记】04-01-决策树简介、熵,04-02-条件熵及计算举例,04-03-信息增益、ID3算法

1. 决策树与熵 1.1 决策树简介 下面有一个贷申请样本表&#xff0c;有许多特征 我们根据特征数据生成一棵树&#xff0c;比如年龄有青年&#xff0c;中年&#xff0c;老年三个类别&#xff0c;那么就有三个分支&#xff0c;分别对应着三种类别。如果是青年那么就看工作&#xf…

八股文场景题

如何预估接口上线后的 QPS 问题引入 这个问题其实是一个非常实际的问题&#xff0c;因为我们在开发需求后&#xff0c;例如&#xff1a;新增了一个接口 有一个步骤是值得做的&#xff0c;那就是预估这个接口的QPS 因为我们是可以去调配对应服务器的数量和运行配置的 例如我…

【Web安全】深入浅出理解“SQL注入-伪静态注入”及空格限制绕过技巧

文章目录什么是伪静态注入&#xff1f;伪静态注入中如何绕过空格限制&#xff1f;1. 用注释符替代空格2. 用不可见字符&#xff08;URL 编码&#xff09;替代3. 用括号分隔语句4. 用特殊符号替代核心逻辑往期文章【Web安全】一次性搞懂 ReDOS 漏洞原理/检测/防御 【Web安全】一…

【读论文】Step-Audio 2 深度解读:迈向工业级语音交互的「全能型选手」

引言:step-Audio升级 语音交互技术,作为人机交互最自然、最直接的方式之一,正以前所未有的速度发展。从简单的语音指令到流畅的语音对话,我们对 AI 的期望越来越高。然而,要让 AI 真正成为我们的“知心伙伴”,仅仅能“听懂”和“说出”还远远不够。 一个理想的语音 AI,…

java web 重定向

目录结构 demo\day20\src\com\demo\service\Dome1.javademo\day20\src\com\demo\service\Dome2.javademo\day20\src\com\demo\service\Dome3.javademo\day20\src\com\demo\service\Dome4.javademo\day20\web\WEB-INF\lib\javax.servlet.jardemo\day20\web\index.jspdemo\day20\…

MySQL(配置)——MariaDB使用

一、简介 MariaDB 和 MySQL 作为两个流行的关系型数据库管理系统&#xff0c;它们的区别可以从多个角度来探讨。尽管 MariaDB 最初是 MySQL 的一个分支&#xff0c;但随着时间的推移&#xff0c;它们逐渐在功能、性能和开发方向上有所不同。MariaDB 是 MySQL 的一个分支&#x…

Web3:赛道划分与发展趋势解析

区块链技术现在已经从单一的加密货币支付系统发展为涵盖金融、艺术、组织治理和社区文化的多元生态系统。这次我们将深入解析 DeFi&#xff08;去中心化金融&#xff09;、NFT&#xff08;非同质化代币&#xff09;、DAO&#xff08;去中心化自治组织&#xff09;与 MEME&#…

LeetCode 283 - 移动零

思路 使用双指针法&#xff0c;一次遍历完成原地修改。 慢指针 slow&#xff1a;指向下一个非零元素应该被放置的位置。快指针 fast&#xff1a;遍历整个数组&#xff0c;寻找非零元素。 当 fast 遇到非零数时&#xff0c;将其值赋给 slow 指向的位置&#xff0c;然后 slow 前进…

8. 网络层

在复杂的网络环境中确定一个合适的路径.1. IP协议1. 基本概念IP协议&#xff1a;提供一种能力(有非常大的概率&#xff0c;做到某事)&#xff0c;把数据报从主机A&#xff0c;跨网络&#xff0c;送到主机B --> 必须要有方式&#xff0c;标识通信两端唯一性&#xff01;&…

【通识】线性代数(Linear Algebra)

线性代数被广泛应用于抽象代数和泛函分析中&#xff1b;通过解析几何&#xff0c;线性代数能被具体表示&#xff0c;线性代数被泛化为算子理论。而非线性模型被近似为线性模型&#xff0c;应用场景多为自然科学和社会科学。 费马和笛卡尔的工作&#xff0c;线性代数出现于十七世…

Qt 嵌入式界面优化技术

在嵌入式系统中&#xff0c;界面性能直接影响用户体验和系统稳定性。由于嵌入式设备通常资源受限&#xff08;如低性能 CPU、有限内存、小尺寸屏幕&#xff09;&#xff0c;需针对性优化 Qt 界面以实现流畅显示和高效交互。本文从渲染引擎、资源管理、布局优化到硬件加速&#…

去除视频字幕 4 : 下一步,打算研究 Video Inpainting (视频修复):

就是说&#xff0c;到现在&#xff0c;才算是真正开始&#xff0c;才发现真正的问题。 尝试去除视频上的字幕&#xff0c;使用 IOPaint, 效果很初级。。。问题描述 请帮我分析此时的效果。 此时的右侧字幕区域&#xff0c;闪烁不停&#xff01;我原本以为效果会很好。实际非常…