天天看點

7個理由:從Java8更新到Java17【翻譯】

作者:IT技術控

簡介

從Java8到Java18,Java已經經曆了漫長的發展曆程(Java20非長期維護版本)。同時也是從Java 8開始,Java生态系統發生了許多變化。其中最明顯的變化是Java版本釋出節奏的改變。Java 8于2014年釋出,而Java 17則是在2021年釋出的,這兩個版本之間相差了7年的時間。然而,2017年9月,Java 平台的主架構師 Mark Reinhold 發出提議,要求将 Java 的功能更新周期從之前的每兩年一個新版本縮減到每六個月一個新版本。該提議獲得了通過,并在提出後不久生效。是以對于Java生态系統的開發者而言,可以更快的使用上Java最新的版本功能。

如果你像我一樣,已經使用了很長時間的Java 8,并且覺得自己需要學習Java的新功能,那麼這篇文章就是為你準備的。

從Java8開始,有許許多多的新功能被添加到了JDK中,但是很明顯不是所有的功能都有用,好用,受大家的歡迎。是以,我在本文中列出了從Java8開始最受Java程式員歡迎的功能,你可以将本文作為一個學習的參考,同時,學會了可以找你同僚吹吹牛逼。

關鍵功能

1.Local Variable Type Inference[局部變量類型推斷]

局部變量類型推斷可以說是Java8以來添加的最受歡迎的功能了,它允許你在不指定類型的情況下聲明局部變量。實際代碼執行時候的類型是通過表達式右側的内容推斷出來的,該功能也稱之為var類型。(沒錯,逐漸Js化)。

例如:var a = 1

Java8 使用局部變量

ini複制代碼URL url = new URL("https://www.baidu.com");
System.out.println(url.getClass());
           

Java10 有了局部變量類型推斷後

ini複制代碼var url = new URL("https://www.baidu.com");
System.out.println(url.getClass());
           

上面的代碼最終的輸出是完全一樣的,但是很明顯,在Java10以後不需要聲明具體的局部變量類型。

ps: Java8中lombok提供了類似的功能,也是var,隻不過需要導包。

java複制代碼

import lombok.var; import org.junit.jupiter.api.Test; import java.net.MalformedURLException; import java.net.URL; //使用 lombok public class JdkTests { @Test public void test1() throws MalformedURLException { var url = new URL("https://www.baidu.com"); System.out.println(url.getClass()); } }

2.switch expression[switch表達式增強]

在Java 14中使用switch表達式時,你不必使用break關鍵字來跳出switch語句,也不必在每個switch case上使用return關鍵字來傳回一個值;相反,你可以傳回整個switch表達式。這種增強的switch表達式使整個代碼看起來更幹淨,更容易閱讀。

Java8中使用switch

csharp複制代碼int flag = 1;

switch(flag) {
    case 1:
        System.out.println("hello");
        break;
    case 2:
        System.out.println("world");
        break;
    case 3:
        System.out.println("hello world");
        break;
    case 4:
        System.out.println("hello");
        break;
    default:
        System.out.println("haha");
}
           

Java14後使用switch

csharp複制代碼int flag = 1;
switch(flag) {
    case 1,4 -> System.out.println("hello");
    case 2 -> System.out.println("world");
    case 3 -> System.out.println("hello world");
    default -> System.out.println("haha");
}
           

3.Text blocks[文本塊]

文本塊是Java 15中出現的一個新特性,它允許你在不使用轉義符号的情況下建立多行字元串。在代碼中寫Json并且還想換行的時候就非常舒服。通過下面的例子,你可以看到如果使用了文本塊,代碼會變得多麼的簡潔和舒服。

Java8中

swift複制代碼String json = "{\n" +
        "  "id": 3,\n" +
        "  "username": "fake_data",\n" +
        "  "password": "fake_data",\n" +
        "  "ips": [\n" +
        "    "fake_data"\n" +
        "  ],\n" +
        "  "firstLoginTime": 29,\n" +
        "  "lastLoginTime": 69,\n" +
        "  "failedAttempts": 62,\n" +
        "  "lockedUntil": "2013-11-20 20:23:23"\n" +
        "}";
           

Java15之後

arduino複制代碼String json = """
    {"id": 3, 
    "username": "fake_data", 
    "password": "fake_data", 
    "ips": ["fake_data"], 
    "firstLoginTime": 29, 
    "lastLoginTime": 69, 
    "failedAttempts": 62, 
    "lockedUntil": "2013-11-20 20:23:23"}
""";
System.out.println(json);
           

4.Records[record類]

record類是Java14引入的一個新的聲明類的方式(之前之後class)。通過該關鍵字你可以用更少的代碼建立一個類似于POJO的類(害,就是個普通的Java類,譬如 User類,Student類等,或者叫實體類也行,不需要分的很細緻)。相較于以往,在此之前大多數開發者使用Lombok來簡化POJO類的寫法(不需要寫get set之類),但現在,使用了record,你不需要使用任何第三方庫,就可以将代碼寫的更加簡潔。在下面的例子中,你可以看到用record代碼會多麼的簡潔。

Java8

typescript複制代碼public class User {
    private String name;
    private String password;

    public User() {

    }
    
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
           

Java8使用lombok

less複制代碼@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private String name;
    private String password;
}
           

使用record

arduino複制代碼public record User(String name,String password) {}
           

測試代碼

csharp複制代碼@Test
public void test7() {
    User user = new User("2","3");
    System.out.println(user.name());
}
           

5.Pattern matching for instanceof[instanceof模式比對]

instanceof模式比對是Java 16中加入的一個新特性。它允許你将instanceof操作符作為一個表達式來使用,并傳回被轉換的對象(不需要強轉了)。在處理嵌套的if-else語句時非常有用。在下面的例子中,你可以看到我們是如何使用instanceof操作符來return Employee對象的,而不使用強轉。

Java8

ini複制代碼if (obj instanceof Employee){
    Employee emp = (Employee)obj;
    return emp.getName();
}
           

使用instanceof模式比對

java複制代碼if (obj instanceof Employee emp){
    return emp.getName();
}
           

6.Sealed classes[密封類]

封閉類是Java 17中加入的一個新特性。它允許你将一個類或接口的繼承限制在一組有限的子類中。簡單來說就是,你有一個 UserService接口,隻想要被 UserServieImpl 實作,以前是不能限制的,現在有了Sealed classes特性之後就可以了,那麼具體如何做到呢?

通過 sealed 修飾符來描述某個類為密封類,同時使用 permits 關鍵字來制定可以繼承或實作該類的類型有哪些。注意 sealed 可以修飾的是類(class)或者接口(interface),是以 permits 關鍵字的位置應該在 extends 或者 implements 之後。

例子:

使用sealed聲明一個UserService隻能夠被UserServiceImpl,UserServiceFinalImpl實作。

kotlin複制代碼public sealed interface UserService permits UserServiceImpl, UserServiceFinalImpl{
}
           

想要實作sealed聲明的接口(繼承類也一樣),子類,或者實作類,需要用final或者non-sealed修飾。

java複制代碼public final class UserServiceFinalImpl implements UserService{
}

public non-sealed class UserServiceImpl implements UserService{
}
           

上面兩者的差別在于:

final修飾的實作類不能被進一步繼承,而一個non-sealed修飾的實作類可以被進一步繼承。

scala複制代碼//進一步繼承
public class UserServiceImplNonSealed extends UserServiceImpl{
}
           

7.Useful NullPointerException

NullPointerExceptions是Java 14中加入的一個新功能。它允許你獲得更多關于NullPointerExceptions的資訊。這在你調試NullPointerExceptions時非常有用。在下面的例子中,你可以看到同樣的代碼在Java 8和Java 14中産生了不同的NullPointerExceptions,但在Java 14中,你可以得到更多關于異常的資訊。 (看到更多的異常棧資訊,能夠更好的進行bug定位)

7個理由:從Java8更新到Java17【翻譯】

小結

本文中我還沒有涵蓋Java 17以來增加的所有功能,但我已經涵蓋了最受歡迎的功能。如果你想了解更多關于Java的新功能,那麼我建議你去看看下面提供的連結。

References

  • JDK 10 features — openjdk.org/projects/jd…
  • JDK 11 features — openjdk.org/projects/jd…
  • JDK 12 features — openjdk.org/projects/jd…
  • JDK 13 features — openjdk.org/projects/jd…
  • JDK 14 features — https://openjdk.org/projects/jdk/14
  • JDK 15 features — openjdk.org/projects/jd…
  • JDK 16 features — openjdk.org/projects/jd…
  • JDK 17 features — openjdk.org/projects/jd…