隨之Java 21正式發(fā)布。該版本是繼JDK 17之后最新的長(zhǎng)期支持版本(LTS),將獲得至少8年的支持!而SpringBoot3和Spring6的最低依賴(lài)就是JDK17了。
在JAVA8的時(shí)代,開(kāi)發(fā)者肯定都使用過(guò)Lombok庫(kù),這個(gè)庫(kù)大大提升了我們的開(kāi)發(fā)效率,少寫(xiě)了很多代碼,但是它也存在很多問(wèn)題,下面我來(lái)細(xì)細(xì)聊一下。
首先我們看下傳統(tǒng)意義上的定義一個(gè)類(lèi):
public class User { private String userName; private String email; private int userId; public User(String username, String email, int userId) { this.userName = userName; this.email = email; this.userId = userId; } public String getUserName() { return username; } public void setUserName(String userName) { this.userName = userName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (userId != user.userId) return false; if (username != null ? !username.equals(user.userName) : user.userName != null) return false; return email != null ? email.equals(user.email) : user.email == null; } @Override public int hashCode() { int result = userName != null ? userName.hashCode() : 0; result = 31 * result + (email != null ? email.hashCode() : 0); result = 31 * result + userId; return result; } @Override public String toString() { return "User{" + "userName='" + userName + '/'' + ", email='" + email + '/'' + ", userId=" + userId + '}'; }}
而使用Lombok后的代碼:
import lombok.Data;@Datapublic class User { private String userName; private String email; private int userId;}
@Data注解會(huì)自動(dòng)生成所有的getter函數(shù)、字段的所有setter函數(shù)、toString函數(shù)、構(gòu)造函數(shù)、hashCode和equals函數(shù)。
@Data 注釋結(jié)合了其他幾個(gè) Lombok 注釋?zhuān)?@Getter、@Setter、@EqualsAndHashCode 和 @toString。如果需要,我們還可以單獨(dú)使用這些注釋。
看上去是很美好,不是嗎?但是仔細(xì)思考下,會(huì)發(fā)現(xiàn)這些問(wèn)題:
那么有什么好的替代方案嗎?Record了解一下?
什么是Record?
Record是 Java 中從 Java 14(作為預(yù)覽功能)開(kāi)始引入的新功能,并在Java 16中正式引入。Records提供了一種簡(jiǎn)潔的方法來(lái)定義主要用于封裝數(shù)據(jù)的簡(jiǎn)單類(lèi)。它們是一種類(lèi),可以根據(jù)類(lèi)的字段自動(dòng)生成常用方法,例如構(gòu)造函數(shù)、 equals()、hashCode()和。toString()
你看到 Record 和 Lombok 之間的相似之處了嗎?他們都在幫助我們實(shí)現(xiàn)同樣的目標(biāo)。
那么如何使用呢?
要使用 Record 定義上述 User 類(lèi),我們只需要這樣做。
public record UserRecord(String userName, String email, int userId) {}
就是這樣。只需一行代碼即可實(shí)現(xiàn)我們用 65 行傳統(tǒng)編碼和 5 行 Lombok 所做的事情。另外,我們不必依賴(lài)第三方庫(kù)。
一旦我們創(chuàng)建了上面的類(lèi),除了toString、hashCode和equals等類(lèi)級(jí)別的方法之外,Java內(nèi)部還定義了三個(gè)final變量及其getter方法。
一旦我們有了用戶Record類(lèi),我們就可以開(kāi)始使用它了。
// Initialize the record.UserRecord userRecord = new UserRecord("test", "test@163.com", 1234);// get the propertiesSystem.out.println(userRecord.email());System.out.println(userRecord.toString());
請(qǐng)注意,getter 方法中沒(méi)有“get”關(guān)鍵字。我們需要直接使用變量名作為方法名。例如,getEmail()我們不是像傳統(tǒng)上那樣使用,而是在調(diào)用 Record 方法時(shí)使用email()。
一旦初始化,我們就無(wú)法設(shè)置 Record 的屬性值。所有變量都是最終的。這意味著記錄是不可變的。
我們可以在記錄中定義實(shí)例和類(lèi)函數(shù)。我們可以定義靜態(tài)變量。我們不能定義實(shí)例變量。
// 類(lèi)(靜態(tài))變量 public static final String invalidEmailMessage = "INVALID EMAIL"; // 實(shí)例變量 - 不允許。會(huì)拋出錯(cuò)誤。 public String defaultEmail = "xxxxx@163.com"; // 類(lèi)函數(shù) public static void sayMyName() { System.out.println("zhangsan"); } // 實(shí)例函數(shù) public String emailDomain() { return this.email.split("@")[1]; }
// 使用對(duì)象userRecord.emailDomain();// 使用 Class 調(diào)用靜態(tài)方法。UserRecord.sayMyName();
Record類(lèi)無(wú)法擴(kuò)展。所有 Record 類(lèi)都隱式擴(kuò)展 Record 類(lèi)。而且Java不允許多重繼承。因此我們的 Record 類(lèi)不能是任何其他類(lèi)的子類(lèi)。
默認(rèn)情況下,記錄也是最終記錄。因此我們不能將它們用作任何其他類(lèi)的父類(lèi)。
該記錄聲明了一個(gè)帶有所有參數(shù)的默認(rèn)構(gòu)造函數(shù)。這種類(lèi)型的構(gòu)造函數(shù)稱(chēng)為規(guī)范構(gòu)造函數(shù)。
public UserRecord(String username, String email, int userId) { this.username = username; this.email = email; this.userId = userId; }
我們可以在構(gòu)造函數(shù)中編寫(xiě)自定義邏輯。
public UserRecord(String username, String email, int userId) { this.username = username; this.email = email; this.userId = userId; if (userId < 1) { throw new IllegalArgumentException("UserId can not be less than 1"); } }
有一個(gè)很棒的功能,我們可以通過(guò)消除不必要的細(xì)節(jié)來(lái)創(chuàng)建一個(gè)緊湊的構(gòu)造函數(shù)。例如,上面具有自定義邏輯的規(guī)范構(gòu)造函數(shù)可以以緊湊的形式重寫(xiě)為:
public UserRecord { if (userId < 1) { throw new IllegalArgumentException("UserId can not be less than 1"); } }
功能 | Lombok | Record |
不變性 | 沒(méi)有 | 是的 |
可擴(kuò)展性 | 是的 | 沒(méi)有 |
樣板代碼 | 減少 | 減少 |
可讀性 | 可能會(huì)更難閱讀 | 更容易閱讀 |
穩(wěn)健性 | 不太穩(wěn)健 | 更堅(jiān)固 |
第三方依賴(lài) | 是的 | 沒(méi)有 |
IDE 兼容性 | 不容易 | 簡(jiǎn)單 |
不會(huì)。就性能而言,使用Java記錄和Lombok注釋沒(méi)有顯著差異。兩者生成的代碼一旦編譯,在性能特征方面與手寫(xiě)代碼沒(méi)有什么不同。生成的代碼由 Java 編譯器優(yōu)化,因此幾乎沒(méi)有性能開(kāi)銷(xiāo)。
本文表明我們應(yīng)該使用記錄來(lái)編寫(xiě)更清晰、更具可讀性的代碼。記錄可以幫助我們減少樣板代碼,而無(wú)需任何第三方庫(kù)。Lombok 與 IDE 存在一些兼容性問(wèn)題。
本文鏈接:http://www.www897cc.com/showinfo-26-19894-0.html給正在使用Lombok的朋友一些建議
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com