layout: post
categories: Java
title: Java 中你絕對沒用過的一個關鍵字?
tagline: by 子悠
tags:
- 子悠
前面的文章給大家介紹瞭如何自定義一個不可變類,沒看過的小夥伴建議去看一下,這節課給大家介紹一個 Java
中的一個關鍵字 Record
,那 Record
關鍵字跟不可變類有什麼關係呢?看完今天的文章你就知道了。友情提示 Record
關鍵字在 Java14
過後才支援的,所以是不是被阿粉說中了,還在使用 Java 8
的你一定沒用過!
不可變類
我們先看一下之前定義的不可變類,程式碼如下。
package com.example.demo.immutable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class Teacher {
private final String name;
private final List<String> students;
private final Address address;
private final Map<String, String> metadata;
public Teacher(String name, List<String> students, Address address, Map<String, String> metadata) {
this.name = name;
this.students = students;
this.address = address;
this.metadata = metadata;
}
public String getName() {
return name;
}
public List<String> getStudents() {
return new ArrayList<>(students);
// return students;
}
public Address getAddress() {
// return address;
return address.clone();
}
public Map<String, String> getMetadata() {
return new HashMap<>(metadata);
// return metadata;
}
}
如果你複製上面程式碼到 IDEA
中,並且剛好你的 JDK
版本是 Java14
之後的話,那麼你就會看到下面這個提示,提示我們可以將 Teacher
這個不可變類轉換為 Record
。怎麼樣是不是很懵,沒關係,我們按照提示操作一下看看會發生什麼。
點完之後我們的程式碼會變成下面的樣子
package com.example.demo.immutable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public record Teacher(String name, List<String> students, Address address, Map<String, String> metadata) {
@Override
public List<String> students() {
return new ArrayList<>(students);
// return students;
}
@Override
public Address address() {
// return address;
return address.clone();
}
@Override
public Map<String, String> metadata() {
return new HashMap<>(metadata);
// return metadata;
}
}
仔細一看你會發現,這是什麼情況,record
是什麼關鍵字,然後類名後面怎麼還有引數?乍一看還以為變成一個方法了。此外我們之前的測試程式碼不用修改任何邏輯,照樣可以正常執行,是不是很神奇?這就是 Record
關鍵字的特性。
Record 關鍵字
看完了 Record
關鍵字的 case
,我們來聊一下 Record
關鍵字是怎麼用的,以及它有什麼特性。
Record
關鍵定義的類是不可變類;Record
定義的類需要將所有成員變數透過引數的形式定義;Record
定義的類預設會生成全部引數的構造方法;Record
定義的類中可以定義靜態方法;Record
定義的類可以提供緊湊的方式進行引數校驗;
上面的五點裡面前三點我們在之前的例子中都可以看出來,在定義和使用的時候可以明顯的看到,如下所示。
public record Teacher(String name, List<String> students, Address address, Map<String, String> metadata) {
}//1,2
Teacher teacher = new Teacher("Java極客技術", students, address, metadata);//3
下面我們看下第四點和第五點,關於第四點我們可以在 Record
類中定義靜態方法用來預設初始化物件,如下所示,透過這種方式我們可以寫出更簡潔的程式碼。
public static Teacher of() {
return new Teacher("Java極客技術", new ArrayList<>(), new Address(), new HashMap<>());
}
public static Teacher of(String name) {
return new Teacher(name, new ArrayList<>(), new Address(), new HashMap<>());
}
在使用的時候,我們就可以直接透過類名引用靜態方法就可以了,如下所示
Teacher teacher = Teacher.of();
接下來我們看看什麼叫緊湊的方式進行引數校驗,試想一下,如果我們需要校驗在溝通 Teacher
物件的時候,student
成員變數不能為空,在我們以前的寫法裡面只要在構造方法裡面進行一下判空就可以了,但是對於 Record
的形式,我們沒有顯示的建立構造方法,那我們應該如何進行判斷呢?答案如下
public Teacher {
if (null == students || students.size() == 0) {
throw new IllegalArgumentException();
}
}
可以看到我們透過一種緊湊的構造方法的形式來進行了引數的校驗,這種寫法跟我們普通的構造方法是不一樣的,沒有方法引數,怎麼樣是不是很神奇。
總結
有的人說 Java
的 Record
的新特性是為了讓大家不使用 Lombok
的,阿粉倒是覺得不見得,畢竟 Lombok
用起來是真的香,而且 Record
也只能是定義不可變類,在某些情況下使用還是有侷限性的,不可變類的使用場景並不是很多。
更多優質內容歡迎關注公眾號【Java 極客技術】,我準備了一份面試資料,回覆【bbbb07】免費領取。希望能在這寒冷的日子裡,幫助到大家。