Java 14带来了5项新特性,看看都有哪些?
Java 14预定于3月17日发布。那么,14版究竟有什么新功能,对于整天写代码、维护代码的Java开发者来说,哪些功能最有用呢?希望你在阅读完本文后,积极地代码中实验这些功能,为Java团队提供反馈,并为Java的发展做出贡献。
1、Switch表达式
Java 14中的switch表达式将会永久存在。switch表达式只是一个“预览”阶段的特性。我想提醒一下,“预览”阶段的特性的目的是为了收集反馈,这些特性可能会随时改变,根据反馈结果,这些特性甚至可能会被移除,但通常所有预览特性最后都会在Java中固定下来。
新的switch表达式的优点是,不再有缺省跳过行为(fall-through),更全面,而且表达式和组合形式更容易编写,因此出现bug的可能性就更低。例如,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; }};
2、文本块
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.\
""";
3、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为Group类型,为什么还要像第一段代码那样在条件代码块中指明obj为Group类型呢?这可能会引发错误。这种更简洁的语法可以去掉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操作符的用例,因为条件就是类型检查,提取操作需要调用适当的方法,或访问特定的字段。换句话说,该预览功能仅仅是个开始,以后该功能肯定能够减少更多的代码冗余,从而降低bug发生的可能性。
4、Record
另一个预览功能就是record。与前面介绍的其他预览功能一样,这个预览功能也顺应了减少Java冗余代码的趋势,能帮助开发者写出更精准的代码。Record主要用于特定领域的类,它的位移功能就是存储数据,而没有任何自定义的行为。
我们开门见山,举一个最简单的领域类的例子:BankTransaction,它表示一次交易,包含三个字段:日期,金额,以及描述。定义类的时候需要考虑多个方面:
构造器
getter方法
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提供了一种方法可以解决这种冗余,可以更清晰地表达目的:这个类的唯一目的就是将数据整合在一起。Record会提供equals、hashCode和toString方法的实现。因此,BankTransaction类可以重构如下:
public record BankTransaction(LocalDate date,
double amount,
String description) {}
通过record,可以“自动”地得到equals,hashCode和toString的实现,还有构造器和getter方法。要想尝试这个例子,需要用preview标志编译该文件:
javac --enable-preview --release 14 BankTransaction.java
record的字段隐含为final。因此,record的字段不能被重新赋值。但要注意的是,这并不代表整个record是不可变的,保存在字段中的对象可以是可变的。
5、NullPointerException
一些人认为,抛出NullPointerException异常应该当做新的“Hello World”程序来看待,因为NullPointerException是早晚会遇到的。玩笑归玩笑,这个异常的确会造成困扰,因为它经常出现在生产环境的日志中,会导致调试非常困难,因为它并不会显示原始的代码。例如,如下代码:
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。因此,无法判断是谁导致了NullPointerException。在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
在以后的版本中,该选项可能会成为默认。这项改进不仅对于方法调用有效,其他可能会导致NullPointerException的地方也有效,包括字段访问、数组访问、赋值等。
6、总结
Java 14提供了几个新的预览版语言特性和更新,能很好地帮助开发者完成日常工作。Java 14还引入了record,这是一种创建精确数据类的新方法。此外,NullPointerException的消息经过了改进,能显示明确的诊断信息。switch表达式也成了Java 14的一部分。文本块功能可以帮你处理多行字符串,这是在引入了两个新的转义序列之后的另一预览功能。还有一项改动就是JDK Flight Recorder的事件流。
免责声明:整理文章为传播相关技术,版权归原作者所有,如有侵权,请联系删除
【免责声明】本文部分系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,如涉及作品内容、版权和其它问题,请在30日内与我们联系,我们会予以重改或删除相关文章,以保证您的权益!
Java开发高端课程免费试学
大咖讲师+项目实战全面提升你的职场竞争力
- 海量实战教程
- 1V1答疑解惑
- 行业动态分析
- 大神学习路径图
相关推荐
更多2022-03-11
2021-03-24
2020-07-22
达内就业喜报
更多>Java开班时间
-
北京 丨 11月27日
火速抢座 -
上海 丨 11月27日
火速抢座 -
广州 丨 11月27日
火速抢座 -
兰州 丨 11月27日
火速抢座 -
杭州 丨 11月27日
火速抢座 -
南京 丨 11月27日
火速抢座 -
沈阳 丨 11月27日
火速抢座 -
大连 丨 11月27日
火速抢座 -
长春 丨 11月27日
火速抢座 -
哈尔滨 丨 11月27日
火速抢座 -
济南 丨 11月27日
火速抢座 -
青岛 丨 11月27日
火速抢座 -
烟台 丨 11月27日
火速抢座 -
西安 丨 11月27日
火速抢座 -
天津 丨 11月27日
火速抢座 -
石家庄 丨 11月27日
火速抢座 -
保定 丨 11月27日
火速抢座 -
郑州 丨 11月27日
火速抢座 -
合肥 丨 11月27日
火速抢座 -
太原 丨 11月27日
火速抢座 -
苏州 丨 11月27日
火速抢座 -
武汉 丨 11月27日
火速抢座 -
成都 丨 11月27日
火速抢座 -
重庆 丨 11月27日
火速抢座 -
厦门 丨 11月27日
火速抢座 -
福州 丨 11月27日
火速抢座 -
珠海 丨 11月27日
火速抢座 -
南宁 丨 11月27日
火速抢座 -
东莞 丨 11月27日
火速抢座 -
贵阳 丨 11月27日
火速抢座 -
昆明 丨 11月27日
火速抢座 -
洛阳 丨 11月27日
火速抢座 -
临沂 丨 11月27日
火速抢座 -
潍坊 丨 11月27日
火速抢座 -
运城 丨 11月27日
火速抢座 -
呼和浩特丨11月27日
火速抢座 -
长沙 丨 11月27日
火速抢座 -
南昌 丨 11月27日
火速抢座 -
宁波 丨 11月27日
火速抢座 -
深圳 丨 11月27日
火速抢座 -
大庆 丨 11月27日
火速抢座