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

开发 后端
Java 是在过去 20 年中一直在市场流行的编程语言。但是最近几年各种替代 Java 的声音不断。

[[353173]]

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

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

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

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

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

1 Try-with-resource 语句

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

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

旧语法

  1. Scanner scanner = null
  2. try { 
  3.     scanner = new Scanner(new File("foo.txt")); 
  4.     while (scanner.hasNext()) { 
  5.         System.out.println(scanner.nextLine()); 
  6.     } 
  7. } catch (FileNotFoundException e) { 
  8.     e.printStackTrace(); 
  9. } finally { 
  10.     if (scanner != null) scanner.close(); 

新语法

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

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

2 switch 表达式

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

旧语法

  1. private String getUserRole(User user){ 
  2.     String userRole = ""
  3.  
  4.     switch(user.getRole()){ 
  5.         case 0: 
  6.             userRole = "Customer"
  7.             break; 
  8.  
  9.         case 1: 
  10.             userRole = "Editor"
  11.             break; 
  12.  
  13.         case 2: 
  14.             userRole = "Admin"
  15.             break; 
  16.  
  17.         default: throw new IllegalStateException("Unexpected value: " + user.getRole()); 
  18.     } 
  19.     return userRole; 

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

新语法

  1. private String getUserRoleV2(User user){ 
  2.  
  3.     return switch(user.getRole()){ 
  4.         case 0 -> "Customer"
  5.         case 1 -> "Editor"
  6.         case 2 : 
  7.             // for multi line expression use 'yield' keyword 
  8.             user.setRights(AuthRights.absolute); 
  9.             yield "Admin"
  10.         default -> throw new IllegalStateException("Unexpected value: " + user.getRole()); 
  11.     }; 

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

3 用 var 初始化

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

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

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

  • 它只能是局部变量(类成员或函数参数不支持)
  • 声明后应立即定义(define)

4 记录 (record)

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

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

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

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

旧语法

  1. public final class FXOrderClassic { 
  2.     private final int units; 
  3.     private final CurrencyPair pair; 
  4.     private final Side side; 
  5.     private final double price; 
  6.     private final LocalDateTime sentAt; 
  7.     private final int ttl; 
  8.  
  9.     public FXOrderClassic(int units, 
  10.                           CurrencyPair pair, 
  11.                           Side side, 
  12.                           double price, 
  13.                           LocalDateTime sentAt, 
  14.                           int ttl) { 
  15.         this.units = units; 
  16.         this.pair = pair; // CurrencyPair is a simple enum 
  17.         this.side = side; // Side is a simple enum 
  18.         this.price = price; 
  19.         this.sentAt = sentAt; 
  20.         this.ttl = ttl; 
  21.     } 
  22.  
  23.     public int units() { 
  24.         return units; 
  25.     } 
  26.  
  27.     public CurrencyPair pair() { 
  28.         return pair; 
  29.     } 
  30.  
  31.     public Side side() { 
  32.         return side; 
  33.     } 
  34.  
  35.     public double price() { return price; } 
  36.  
  37.     public LocalDateTime sentAt() { 
  38.         return sentAt; 
  39.     } 
  40.  
  41.     public int ttl() { 
  42.         return ttl; 
  43.     } 
  44.  
  45.     @Override 
  46.     public boolean equals(Object o) { 
  47.         if (this == o) return true
  48.         if (o == null || getClass() != o.getClass()) 
  49.             return false
  50.  
  51.         FXOrderClassic that = (FXOrderClassic) o; 
  52.  
  53.         if (units != that.units) return false
  54.         if (Double.compare(that.price, price) != 0) 
  55.             return false
  56.         if (ttl != that.ttl) return false
  57.         if (pair != that.pair) return false
  58.         if (side != that.side) return false
  59.         return sentAt != null ? 
  60.                 sentAt.equals(that.sentAt) : that.sentAt == null
  61.     } 
  62.  
  63.     @Override 
  64.     public int hashCode() { 
  65.         int result; 
  66.         long temp
  67.         result = units; 
  68.         result = 31 * result + 
  69.                 (pair != null ? pair.hashCode() : 0); 
  70.         result = 31 * result + 
  71.                 (side != null ? side.hashCode() : 0); 
  72.         temp = Double.doubleToLongBits(price); 
  73.         result = 31 * result + 
  74.                 (int) (temp ^ (temp >>> 32)); 
  75.         result = 31 * result + 
  76.                 (sentAt != null ? sentAt.hashCode() : 0); 
  77.         result = 31 * result + ttl; 
  78.         return result; 
  79.     } 
  80.  
  81.     @Override 
  82.     public String toString() { 
  83.         return "FXOrderClassic{" + 
  84.                 "units=" + units + 
  85.                 ", pair=" + pair + 
  86.                 ", side=" + side + 
  87.                 ", price=" + price + 
  88.                 ", sentAt=" + sentAt + 
  89.                 ", ttl=" + ttl + 
  90.                 '}'
  91.     } 

新语法

  1. public record FXOrder(int units, 
  2.                       CurrencyPair pair, 
  3.                       Side side, 
  4.                       double price, 
  5.                       LocalDateTime sentAt, 
  6.                       int ttl) {} 

5 增强的 instance of

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

旧语法

  1. private Entries getEntries(User user){ 
  2.     if (user instanceof Editor) { 
  3.         Editor editor = (Editor) user
  4.  
  5.         // use editor specific methods 
  6.         var entries = editor.getEntries(); 
  7.         return entries; 
  8.     } 
  9.      
  10.     return null

新语法

  1. private Entries getEntries(User user){ 
  2.      
  3.     if (user instanceof Editor editor) { 
  4.         // use group specific methods 
  5.         var entries = editor.getEntries(); 
  6.         return entries; 
  7.     } 
  8.  
  9.     return null

6 文本块

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

旧语法

  1. String html = "<HTML>" + 
  2. "\n\t" + "<BODY>" + 
  3. "\n\t\t" + "<H2>\"Hurray! Java 14 is here\"</H2>" + 
  4. "\n\t" + "</BODY>" + 
  5. "\n" + "</HTML>"

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

新语法

  1. String html = ""
  2. <HTML> 
  3.   <BODY> 
  4.     <H2>"Hurray! Java 14 is here"</H2> 
  5.   </BODY> 
  6. </HTML> 
  7. """; 

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

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

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

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

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

  • getData()返回一个空值
  • getBucket()返回一个空值

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

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

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

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

-XX:+ShowCodeDetailsInExceptionMessages

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

英文原文:

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

本文转载自微信公众号「高可用架构」,可以通过以下二维码关注。转载本文请联系高可用架构公众号。

 

责任编辑:武晓燕 来源: 高可用架构
相关推荐

2019-11-05 16:51:41

JavaScript数据es8

2019-03-04 09:39:41

Java开发代码

2013-10-21 17:57:54

2012-03-24 21:02:41

iOS

2022-01-17 22:33:37

Java特定类型

2014-08-21 10:34:11

Java 9Java

2015-06-29 09:40:10

Rails新特性

2021-02-22 11:51:15

Java开发代码

2014-07-15 14:48:26

Java8

2020-09-17 13:10:54

Java1编程语言新特性

2015-08-28 09:43:49

Java 8新特性处理集合

2017-11-22 09:57:22

HTML5存储代码

2011-12-14 16:15:17

MySQL

2021-10-12 07:15:03

C++20特性

2022-03-09 08:14:24

CSS容器container

2020-04-26 10:52:37

LinuxUbuntu 20.0Ubuntu 18.0

2014-12-04 10:47:18

Java 9

2009-07-08 09:35:53

Java ServleServlet 3.0

2014-05-05 09:58:01

2013-05-02 09:14:19

Java 8Java 8的新特性
点赞
收藏

51CTO技术栈公众号