Java 14带来了许多新功能
2020年2月27日
Java 14计划于3月17日发布。版本14包含的JEP(Java增强提案)比Java 12和13的总和还多。那么,对于每天编写和维护代码的Java开发人员来说,最重要的是什么呢?
在本文中,我研究了以下主要方面:
- 改进的switch表达式,该表达式最初在Java 12和Java 13中作为预览出现,现在已完全成为Java 14的一部分
- 模式匹配
instanceof
(一种语言功能) - 有用
NullPointerException
的(JVM功能)
如果您阅读本文并尝试在代码库中使用其中的某些功能,建议您通过向Java团队提供反馈来分享您的经验。这样,您就有机会为Java的发展做出贡献。
切换表达式
在Java 14中,switch表达式变为永久性的。如果您需要复习一下什么是switch表达式,那么在前 两篇文章中已广泛讨论了它们。
在早期版本中,switch表达式是“预览”功能。提醒一下,将特征指定为“预览”以收集反馈,并且根据反馈可能会更改甚至删除这些特征。但预计大多数最终将在Java中永久化。
新的switch表达式的优点包括由于没有掉落行为,穷举以及由于表达式和复合形式而易于编写,从而减少了错误的范围。作为一个刷新示例,switch表达式现在可以利用箭头语法,例如在以下示例中:
var log = switch (event) {
case PLAY -> "User has triggered the play button";
case STOP, PAUSE -> "User needs a break";
default -> {
String message = event.toString();
LocalDateTime now = LocalDateTime.now();
yield "Unknown event " + message +
" logged on " + now;
}
};
文字块
Java 13引入了文本块作为预览功能。文本块使使用多行字符串文字更加容易。此功能将通过Java 14进行第二轮预览,并进行了一些调整。作为复习,编写带有许多字符串连接和转义序列的代码以提供适当的多行文本格式非常普遍。下面的代码显示了HTML格式的示例:
String html = "<HTML>" +
"\n\t" + "<BODY>" +
"\n\t\t" + "<H1>\"Java 14 is here!\"</H1>" +
"\n\t" + "</BODY>" +
"\n" + "</HTML>";
使用文本块,您可以简化此过程并使用界定文本块开头和结尾的三个引号来编写更优雅的代码:
String html = """
<HTML>
<BODY>
<H1>"Java 14 is here!"</H1>
</BODY>
</HTML>""";
与普通字符串文字相比,文本块还提供了更高的表达能力。您可以在较早的文章中了解有关此内容的更多信息。
Java 14中添加了两个新的转义序列。首先,您可以使用新的\s
转义序列表示单个空格。其次,您可以使用反斜线\
来禁止在行尾插入新行字符。当您想分隔很长的行以简化文本块内的可读性时,这很有用。
例如,当前处理多行字符串的方法是
String literal =
"Lorem ipsum dolor sit amet, consectetur adipiscing " +
"elit, sed do eiusmod tempor incididunt ut labore " +
"et dolore magna aliqua.";
使用\
文本块中的转义序列,可以将其表示为:
String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing \
elit, sed do eiusmod tempor incididunt ut labore \
et dolore magna aliqua.\
""";
instanceof的模式匹配
Java 14引入了预览功能,该功能有助于消除对在进行条件instanceof
检查之前进行显式强制转换的需求。例如,考虑以下代码:
if (obj instanceof Group) {
Group group = (Group) obj;
// use group specific methods
var entries = group.getEntries();
}
可以使用预览功能将其重构为:
if (obj instanceof Group group) {
var entries = group.getEntries();
}
因为条件检查断言obj
是type Group
,所以为什么要在第一个代码段中用条件块再次说该obj
类型Group
?这种需求可能会增加错误的范围。
较短的语法将删除典型Java程序中的许多强制转换。(A 研究论文从2011年提出了一个相关的语言特性报告说,所有铸件约24%遵循instanceof
的条件语句。)
JEP 305涵盖了此更改,并从Joshua Bloch 的Effective Java书中指出了一个示例,该示例通过以下相等方法进行说明:
@Override public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString) &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
通过删除冗余的显式强制转换为,可以将前面的代码简化为以下形式CaseInsensitiveString
:
@Override public boolean equals(Object o) {
return (o instanceof CaseInsensitiveString cis) &&
cis.s.equalsIgnoreCase(s);
}
这是一个有趣的预览功能,因为它为更广泛的模式匹配打开了大门。模式匹配的思想是为语言功能提供方便的语法,以根据某些条件提取对象的成分。instanceof
运算符就是这种情况,因为条件是类型检查,并且提取操作正在调用适当的方法或访问特定字段。
换句话说,此预览功能仅仅是个开始,您可以期待一种语言功能,它可以帮助进一步减少冗长性,从而减少错误的可能性。
记录
商店中还有另一种预览语言功能:记录。像到目前为止提出的其他想法一样,此功能遵循减少Java冗长并帮助开发人员编写更简洁的代码的趋势。记录集中在某些域类上,这些类仅用于将数据存储在字段中,并且不声明任何自定义行为。
为了直接解决该问题,请使用一个简单的域类,该类BankTransaction
通过三个字段对交易进行建模:日期,金额和描述。声明类时,您需要担心多个组件:
- 构造函数
- get方法
toString()
hashCode()
和equals()
此类组件的代码通常由IDE自动生成,并占用大量空间。这是BankTransaction
该类的完整生成的实现:
public class BankTransaction {
private final LocalDate date;
private final double amount;
private final String description;
public BankTransaction(final LocalDate date,
final double amount,
final String description) {
this.date = date;
this.amount = amount;
this.description = description;
}
public LocalDate date() {
return date;
}
public double amount() {
return amount;
}
public String description() {
return description;
}
@Override
public String toString() {
return "BankTransaction{" +
"date=" + date +
", amount=" + amount +
", description='" + description + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BankTransaction that = (BankTransaction) o;
return Double.compare(that.amount, amount) == 0 &&
date.equals(that.date) &&
description.equals(that.description);
}
@Override
public int hashCode() {
return Objects.hash(date, amount, description);
}
}
Java的14提供了一种方法来去除冗长,使意图明确指出,所有你想要的是,只有拥有的实现数据聚合在一起的一类equals
,hashCode
和toString
方法。您可以BankTransaction
按以下方式重构:
public record BankTransaction(LocalDate date,
double amount,
String description) {}
有了记录,你“自动”得到的实现equals
,hashCode
以及toString
除了构造函数和getter。
要尝试该示例,请记住您需要使用预览标志来编译文件:
javac --enable-preview --release 14 BankTransaction.java
记录的字段是隐式的final
。这意味着您无法重新分配它们。但是请注意,这并不意味着整个记录都是不变的。存储在字段中的对象本身可以是可变的。
如果您对有关记录的更详细的文章感兴趣,请参阅Java杂志上 Ben Evans的最新文章。
敬请关注。从教育的角度来看,唱片还为下一代Java开发人员提出了有趣的问题。例如,如果您指导初级开发人员,那么什么时候应该在课程中引入记录:在引入OOP和类之前或之后?
有用的NullPointerExceptions
有人说throw NullPointerException
应该是Java中新的“ Hello world”,因为您无法逃避它们。除了笑话,它们还导致挫败感,因为当代码在生产环境中运行时,它们经常出现在应用程序日志中,这可能使调试变得困难,因为原始代码不容易获得。例如,考虑以下代码:
var name = user.getLocation().getCity().getName();
在Java 14之前,您可能会收到以下错误:
Exception in thread "main" java.lang.NullPointerException
at NullPointerExample.main(NullPointerExample.java:5)
不幸的是,如果在第5行,则有一个具有多个方法调用的赋值- getLocation()
和- getCity()
两者都可能返回null。实际上,变量user
也可以为null。因此,目前尚不清楚是什么原因引起的<strong>NullPointerException</strong>
。
现在,使用Java 14,有一个新的JVM功能,通过它您可以收到更多信息的诊断信息:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Location.getCity()" because the return value of "User.getLocation()" is null
at NullPointerExample.main(NullPointerExample.java:5)
该消息现在具有两个明确的组成部分:
- 结果:
Location.getCity()
无法调用。 - 原因:的返回值为
User.getLocation()
null。
仅当您使用以下标志运行Java时,增强型诊断才有效:
-XX:+ShowCodeDetailsInExceptionMessages
这是一个例子:
java -XX:+ShowCodeDetailsInExceptionMessages NullPointerExample
在Java的未来版本中,这项功能可能会被默认启用,据报道在这里。
此增强功能不仅可用于方法调用,而且还可在可能导致的其他地方使用NullPointerException
,包括字段访问,数组访问和赋值。
结论
在Java 14中,有新的预览语言功能和更新可帮助开发人员进行日常工作。例如,Java 14引入了instanceof
模式匹配,这是减少显式转换的一种方法。而且,Java 14引入了记录,这是一种新的结构,用于简洁地声明仅用于聚合数据的类。此外,NullPointerException
消息已通过更好的诊断得到了增强,并且开关表达式现在已成为Java 14的一部分。文本块是一种可帮助您处理多行字符串值的功能,在引入了两个新的转义序列之后,将进行另一轮预览。Java操作的一部分技术人员可能会感兴趣的另一项更改是JDK Flight Recorder中的事件流。该选项在本埃文斯的这篇文章。
关注公众号会,每天获取一篇新文章
Java 14带来了许多新功能的更多相关文章
- iOS 14.5 有啥新功能?Apple Watch 也能解锁 iPhone 了
转: iOS 14.5 有啥新功能?Apple Watch 也能解锁 iPhone 了 苹果今天发布了即将发布的 iOS 14.5 和 iPadOS 14.5 更新的第一个 Beta 版本,我们在其中 ...
- Java Math 类中的新功能--浮点数
Java™语言规范第 5 版向 java.lang.Math和 java.lang.StrictMath添加了 10 种新方法,Java 6 又添加了 10 种.这个共两部分的系列文章的 第 1 部分 ...
- Java 14 新功能介绍
不做标题党,认认真真写个文章. 文章已经收录在 Github.com/niumoo/JavaNotes 和未读代码博客,点关注,不迷路. Java 14 早在 2019 年 9 月就已经发布,虽然不是 ...
- Java 18 新功能介绍
文章持续更新,可以关注公众号程序猿阿朗或访问未读代码博客. 本文 Github.com/niumoo/JavaNotes 已经收录,欢迎Star. Java 18 在2022 年 3 月 22 日正式 ...
- Java 19 新功能介绍
点赞再看,动力无限. 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Java 19 在2022 年 9 ...
- Java 17 将要发布,补一下 Java 13 中的新功能
本文章属于Java 新特性教程 系列,已经收录在 Github.com/niumoo/JavaNotes ,点个赞,不迷路. 自从 Oracle 调整了 Java 的版本发布节奏之后,Java 版本发 ...
- Java 14 令人期待的 5 大新特性,打包工具终于要来了
随着新的 Java 发布生命周期的到来,新版本预计将于 2020 年 3 月发布,本文将对其中的 5 个主要特性作些概述. Java 13刚刚发布给开发人员使用不久,最新版本的JDK于2019年9月发 ...
- Java 14 开箱,它真香香香香
Java 14 已经发布有一周时间了,我准备来开个箱,和小伙伴们一起来看看新特性里面都有哪些好玩的.我们程序员应该抱着尝鲜.猎奇的心态,否则就容易固步自封,技术停滞不前.先来看看 Java 14 都有 ...
- Java 8 到 Java 14,改变了哪些你写代码的方式?
前几天,JDK 14 正式发布了,这次发布的新版本一共包含了16个新的特性. 其实,从Java8 到 Java14 ,真正的改变了程序员写代码的方式的特性并不多,我们这篇文章就来看一下都有哪些. La ...
随机推荐
- 理解session及微信小程序使用session
session介绍 由于Http是无状态的协议,所以服务端需要记录用户的状态时,就需要某种机制来识别具体的用户,实现这个机制的方式就是session. 典型的场景比如购物车,当你点击下单按钮时,由于H ...
- 几种常见的app推广形式
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 服务器开发 Ubuntu
一.Ubuntu安装: 为什么用Ubuntu,作为服务器初学者开发,如果真的要买苹果系统电脑性价比不高,所以在window系统中安装Linux虚拟机是不二之选.为什么用Ubuntu不多说了,开始安装吧 ...
- 2018-ECCV-PNAS-Progressive Neural Architecture Search-论文阅读
PNAS 2018-ECCV-Progressive Neural Architecture Search Johns Hopkins University(霍普金斯大学) && Go ...
- python库-collections模块Counter类
Counter类主要是用来跟踪值出现的次数.它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value. demo: all_words = [] # 列表里面是汉字(可 ...
- JavaScript (二) js的基本语法 - - 运算符、流程控制
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.运算符 1.一元运算符 ++ -- 都是运算符 ++ 和 -- 可以分为:前+ 和后+ and 前- ...
- Spring Cloud 系列之 Apollo 配置中心(三)
本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Apollo 配置中心(一) Spring Cloud 系列之 Apollo 配置中心(二) 本篇文章讲解 Apol ...
- Java实现 LeetCode 791 自定义字符串排序(桶排序)
791. 自定义字符串排序 字符串S和 T 只包含小写字符.在S中,所有字符只会出现一次. S 已经根据某种规则进行了排序.我们要根据S中的字符顺序对T进行排序.更具体地说,如果S中x在y之前出现,那 ...
- (Java实现) 均分纸牌
题目描述 有 N 堆纸牌,编号分别为 1,2,-, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以在任一堆上取若于张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 ...
- Java中线程的操作状态
start() 线程开始运行 sleep() 当前线程暂停休息 括号里面是多长时间以毫秒为单位 wait() 当前线程等待 notify() 线程wait后用这个方法唤醒 notifyAll() 把所 ...