17

你可能未曾使用的新 Java 特性

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ%3D%3D&%3Bmid=2653553894&%3Bidx=1&%3Bsn=9a021c34fc2a920b72e351a50c4d7df7
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Java 是在过去 20 年中一直在市场流行的编程语言。

但是最近几年各种替代 Java 的声音不断。

与 Python,Kotlin,Swift 等现代编程语言相比,开发人员抱怨 Java 过时的编程语法。

但是很多人不知道的是,Java 新版做了很多改进,并为开发人员提供了更有效的方式来编写代码。

如果您想用 Java  更轻松编写简洁和优雅的代码,可以参考以下一些建议,这些语法在 JDK 14 已经提供。

1 Try-with-resource 语句

使用 try-catch 块处理异常,通常需要通过 finally 块来添加清除代码。现在使用 try with resource 语法,开发人员就不用自己操心资源释放。

我们可以在 try 括号内添加资源,以便在 try-catch 块执行后关闭或清理该资源

旧语法

Scanner scanner = null;
try {
scanner = new Scanner(new File("foo.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) scanner.close();
}

新语法

try (Scanner scanner = new Scanner(new File("foo.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}

这将大大减少关闭流或数据库连接的代码行,并减少由于忘记关闭流/连接而导致各种错误的问题。

2  switch  表达式

开发人员经常遇到需要从条件块返回值的情况,但是旧的语法不好解决。

旧语法

private String getUserRole(User user){
String userRole = "";


switch(user.getRole()){
case 0:
userRole = "Customer";
break;


case 1:
userRole = "Editor";
break;


case 2:
userRole = "Admin";
break;


default: throw new IllegalStateException("Unexpected value: " + user.getRole());
}
return userRole;
}

就像 Swift 这些现代语言一样,Java 12 引入了 switch 表达式,你可以根据条件返回值。

新语法

private String getUserRoleV2(User user){


return switch(user.getRole()){
case 0 -> "Customer";
case 1 -> "Editor";
case 2 :
// for multi line expression use 'yield' keyword
user.setRights(AuthRights.absolute);
yield "Admin";
default -> throw new IllegalStateException("Unexpected value: " + user.getRole());
};
}

这大大减少了项目中的 LOC(代码行),并使修改相对容易。

用 var 初始化

Java 本质上是严格类型的语言,使用严格类型定义是开发人员偏好的问题。但是支持类型推断可以降低代码复杂性,Java 10 增加了对局部变量的类型推断的支持。

private void init(){
var str = "Java 10"; // infers String
var list = new ArrayList<String>();
var stream = list.stream(); // infers Stream<String>


}

但 Java 仍然是一种静态类型的语言,仅在有足够的信息可用于初始化时才推断类型。因此如果变量满足以下条件,则使用 var 初始化是合法的:

  • 它只能是局部变量(类成员或函数参数不支持)

  • 声明后应立即定义(define)

记录 (record)

使用 Java 最常见的抱怨之一,需要编写大量代码来使类可用,例如一堆 toString 或 equals 定义,因此代码看起来很冗长。Java 14 提供了 Record 语法,使类型声明更加简洁,当我们需要在一个类名下绑定多个值时,它非常有用。

这是 Oracle 网站上的一篇文章示例,展示了使用记录的优势

var order = new FXOrderClassic(1, 
CurrencyPair.GBPUSD,
Side.Bid, 1.25,
LocalDateTime.now(),
1000);

像这样的标准对象的调用,需要定义类型 FXOrderClassic。

旧语法

public final class FXOrderClassic {
private final int units;
private final CurrencyPair pair;
private final Side side;
private final double price;
private final LocalDateTime sentAt;
private final int ttl;


public FXOrderClassic(int units,
CurrencyPair pair,
Side side,
double price,
LocalDateTime sentAt,
int ttl) {
this.units = units;
this.pair = pair; // CurrencyPair is a simple enum
this.side = side; // Side is a simple enum
this.price = price;
this.sentAt = sentAt;
this.ttl = ttl;
}


public int units() {
return units;
}


public CurrencyPair pair() {
return pair;
}


public Side side() {
return side;
}


public double price() { return price; }


public LocalDateTime sentAt() {
return sentAt;
}


public int ttl() {
return ttl;
}


@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;


FXOrderClassic that = (FXOrderClassic) o;


if (units != that.units) return false;
if (Double.compare(that.price, price) != 0)
return false;
if (ttl != that.ttl) return false;
if (pair != that.pair) return false;
if (side != that.side) return false;
return sentAt != null ?
sentAt.equals(that.sentAt) : that.sentAt == null;
}


@Override
public int hashCode() {
int result;
long temp;
result = units;
result = 31 * result +
(pair != null ? pair.hashCode() : 0);
result = 31 * result +
(side != null ? side.hashCode() : 0);
temp = Double.doubleToLongBits(price);
result = 31 * result +
(int) (temp ^ (temp >>> 32));
result = 31 * result +
(sentAt != null ? sentAt.hashCode() : 0);
result = 31 * result + ttl;
return result;
}


@Override
public String toString() {
return "FXOrderClassic{" +
"units=" + units +
", pair=" + pair +
", side=" + side +
", price=" + price +
", sentAt=" + sentAt +
", ttl=" + ttl +
'}';
}
}

新语法

public record FXOrder(int units,
CurrencyPair pair,
Side side,
double price,
LocalDateTime sentAt,
int ttl) {}

增强的 instance of

Java 14 引入了 instanceof 模式匹配的功能,这意味着在使用 instanceof 的实例类型检查时,不再需要显式的类型转换。

旧语法

private Entries getEntries(User user){
if (user instanceof Editor) {
Editor editor = (Editor) user;


// use editor specific methods
var entries = editor.getEntries();
return entries;
}

return null;
}

新语法

private Entries getEntries(User user){

if (user instanceof Editor editor) {
// use group specific methods
var entries = editor.getEntries();
return entries;
}


return null;
}

6 文本块

支持文本块并不是什么新鲜事,但在 Java 中却是工程师期待已久的功能。Java 开发人员总是渴望以更简单的方式打印多行字符串文字,而不使用讨厌的串联。Java 新版支持多行字符串文字。

旧语法

String html = "<HTML>" +
"\n\t" + "<BODY>" +
"\n\t\t" + "<H2>\"Hurray! Java 14 is here\"</H2>" +
"\n\t" + "</BODY>" +
"\n" + "</HTML>";

使用三引号 ,就可以使用此功能,该功能在使用结构化字符串时非常方便,例如以一定的对齐方式和间距编写文件或添加多行 html 块

新语法

String html = """
<HTML>
<BODY>
<H2>"Hurray! Java 14 is here"</H2>
</BODY>
</HTML>
""";

有意义的 NPE (空指针)消息

空指针异常(NPE)一直是 Java 开发人员的噩梦,并且是开发人员遇到的最常见的问题。

但是 NPE 消息常常不能提供有关该问题的足够信息。

var task = new Task();
final boolean isDataConsumed = task.getData().getBucket().isConsumed;

在代码段中,可能存在多个故障点,例如

  • getData()返回一个空值

  • getBucket()返回一个空值

但以下 NPE 报错未提供有关该问题的足够详细信息。

yIJVVj.png!mobile

为了解决此问题,Oracle 添加 JEP 358,提供有用的 NullPointExceptions

NullPointerException 通过精确描述哪个变量来提高 JVM 生成错误信息的可用性。

你可以通过在 Java 命令中添加以下标志来使用此功能

-XX:+ShowCodeDetailsInExceptionMessages

使用该标志,JVM 将提供更多有意义的信息,以便跟踪确切的故障点

yi22Yb.png!mobile

英文原文:

https://medium.com/swlh/working-with-new-generation-of-java-236e2dc38316

参考阅读:

本文由高可用架构翻译,技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。

高可用架构

改变互联网的构建方式

vEjQNvu.jpg!mobile 长按二维码 关注「高可用架构」公众号

像这样的标准对象的调用需要定义类型FXOrderClassic,可以通过以下方式实现


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK