iT邦幫忙

2023 iThome 鐵人賽

DAY 1
0
Software Development

Java 17 新登場系列 第 1

Day 1 - 從 Java 8 到 17 的 7 個理由

  • 分享至 

  • xImage
  •  

Java 18

香香濃濃的 Java 17

Java 是筆者進入 IT 業界的啟蒙老師,歷經了十個年頭,翻過了多少語言的山頭(Python, Golang, C++, PHP...),最近又回鍋寫 Java ,因為她的丰姿,我這個傻瘋子願意在為她奉獻下一個十年,不為別的,只因為她可靠而高效、容易親近但有深度,值得信賴偶爾帶點俏皮,同時她也無所不能,她的好只有老公(程師)懂得!

從 Oracle 大大接手 Java 後,從 8 ~ 17 只花了 (2014 3月 ~ 2022 3月) 8 年,這相當於 Java 從 6 到 8 的時間 (2006 12 月 ~ 2014 3月) ,究竟是 Oracle 對於大版本號碼的解讀不同,還是 Oralce 真的讓他飛了起來,讓我們用 30 天來一探究竟。

7 個理由

1. 區域變數型別推斷:

允許用更簡潔的 var 來宣告型別,會根據等號右邊的型別做型別推斷

//Java 8
URL url = new URL(”https://www.google.com”);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(”GET”);

//Java 10
var url = new URL(”https://www.google.com”);
var connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(”GET”);

可惜的是,不能用在 Lambda 表達式,之後會介紹 Lambda 表達式其實是一種(函式)類別物件,用函式表達的一種類別物件,可以被指派給物件參考,意即 Lambda 表達式不能指派給 var 物件,不幸中的小確幸是:可以用在 lambda 表達式中的 參數宣告-.-

// compile error!
var fun = MyObject::mySpecialFunction;

// .....mmmmm 其實可以直接不寫 var = =
boolean isThereAneedle = stringsList.stream()
  .anyMatch((@NonNull var s) -> s.equals(“needle”));

2. Records

大家肯定有用過 lombok 吧,lombok 的流行程度同時也是 Java 迷無聲抗議的程度,Records大概就是官方給的回應吧,這個回應超簡短的唷,直接看例子:

// Java 8
@Data
@AllArgConstructor
class Pojo {
  private String pojoName;
  private String pojoAge;
  public Pojo(String pojoName, String pojoAge){
      this.pojoName = pojoName;
      this.pojoAge = pojoAge;
  }
  ... getter & setter
}

// Java 16
record Pojo(String pojoName, String pojoAge){}

定義 record 類別時,不能使用 hashCode、equals、toString、wait、notify 等作為欄位名稱,record 也不能被繼承。

3. 增強的 switch 語句

從 Java 8 到 17 ,增強的 switch 可以有返回值了,如果 case 語句內的程式區塊只有一行,直接回傳,但如果有多行程式,可以使用關鍵字 'yield'

DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
boolean freeDay = false;

// Java 8
switch(dayOfWeek){
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
        freeDay = false;
    case SATURDAY:
    case SUNDAY:
        freeDay = true;
    default:
        break;
}

// Java 14
boolean freeDay = switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false;
    case SATURDAY, SUNDAY -> true;
};

// Using yield
boolean freeDay = switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
        System.out.println("Work work work");
        yield false;
    }
    case SATURDAY, SUNDAY -> {
        System.out.println("Yey, a free day!");
        yield true;
    }
};

4. 文字區塊

這真的是千呼萬喚始出來的,光這點加上效能上的改進,就值得升級 17 了

// Java 8
String longSQL = "SELECT * FROM user u " +
                 "LEFT JOIN user_info ui ON u.id=user_info.user_id"

// Java 15
String longSQL = """
SELECT * FROM user u 
LEFT JOIN user_info ui ON u.id=user_info.user_id
"""

5. instanceof 模式匹配

強制型別轉換一直都是工程師眼裡的一顆老鼠屎啊,Java 17 把屎變不見啦

// Java 8
if(obj instanceof Employee){
    Employee emp = (Employee)obj;
    return emp.getName();
}

// Java 16
if(obj instanceof Employee emp){
    return emp.getName();
}

6. Sealed 類別(Seal Class)

Sealed class宣告類別(class)及介面(interface)可被哪些類別繼承或實作,換句話說未被sealed class允許的類別或介面則不能繼承或實作。目的是避免被任意繼承造成的混亂。
public sealed class Parent premits Child1, Child2 {}

繼承 sealed class 只能是 non-sealed 或是 final 類別,原因很簡單,表示不能在宣告可以被誰誰誰繼承。
所以以下語法會有編譯錯誤:
public final class Teacher extends Parent {} //compile error

7. 更有用的 NullPointerException

以前的 NullPointerException 只會丟訊息:

Exception in thread "main":
java.lang.NullPointerException
    at Ironman.main(ironman_1.java: 12)

Java 17 會跟你說:

Exception in thread "main":
java.lang.NullPointerException: Cannot read field "x"
because "p" is null
    at Ironman.main(ironman_1.java: 12)

參考資料:

https://levelup.gitconnected.com/7-reasons-to-migrate-from-java-8-to-java-17-b8cb031b7af8
https://matthung0807.blogspot.com/2022/04/java-sealed-class.html
https://pretius.com/blog/java-17-features/


下一篇
Day 2 - Lambda 表達式
系列文
Java 17 新登場8
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言