您好,登錄后才能下訂單哦!
Lombok如何在Java項(xiàng)目中使用?相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
安裝 Lombok
使用 Lombok 之前我們先要在所使用的 IDE 中進(jìn)行集成安裝,這里以 IDEA 為例,安裝步驟十分簡單:
前往 File -> Settings -> Plugin -> Marketplace ,搜索 Lombok
選擇搜索結(jié)果 Lombok ,點(diǎn)擊 Install 安裝。
安裝完成后重啟即可。
基于 Eclipse 的 Lombok 插件安裝方法這里就不詳細(xì)描述了,官方也給了對應(yīng)的文檔說明:projectlombok.org/setup/eclip…
在 IDE 安裝了 Lombok 插件后,我們就可以在 pom.xml 文件中添加 Lombok 的依賴進(jìn)行使用了。
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> <scope>provided</scope> </dependency>
注意:pom 依賴設(shè)置 scope 為 provided,是為了讓 Lombok 庫不被打包進(jìn)程序。
2.2 @Getter/@Setter
通常我們編寫實(shí)體類無論多少個(gè)字段,都要為其提供 getter 和 setter 方法,如下面的示例類 User.java
我們常會(huì)遇到這種情況:某個(gè)實(shí)體類新增和修改某個(gè)字段,我們都需要單獨(dú)處理調(diào)整,十分麻煩并且重復(fù)。
這時(shí)候如果我們使用 Lombok 提供 @Getter/@Setter 注解就能幫我們省去 getter 和 setter 方法的維護(hù),由 Lombok 對 User 類自動(dòng)生成 getter 和 setter 方法,兩者最終的字節(jié)碼時(shí)一樣的,而我們現(xiàn)在在 User.java 上編寫的代碼僅僅 7 行即可:
@Getter @Setter public class User { private Integer id; private String username; private String password; }
然后用測試類 UserTests.java 測試結(jié)果如下:
public class UserTests { @Test public void test() { User user = new User(); user.setUsername("one"); user.setPassword("zxc123"); Assert.assertEquals(user.getUsername(), "one"); Assert.assertEquals(user.getPassword(), "zxc123"); } }
@Getter/@Setter 注解不僅可以使用在類上,還可以使用在字段上,這樣就是表示針對該字段自動(dòng)生成 getter /setter 方法。
@Getter @Setter private String password;
這里該注解使用在類上,還是在字段上的區(qū)別就是,如果注解使用在類上,只針對這個(gè)類的非靜態(tài)字段有效。
需要注意的一點(diǎn)是:如果 @Getter 注解修飾了 boolean 類型的變量,其生成的 getter 方法簽名是 isXXX 形式,而不是 getXXX形式。
除此之外,@Getter/@Setter 還提供訪問權(quán)限控制的屬性 lombok.AccessLevel value(), 默認(rèn)為 PUBLIC,而其他選值都是枚舉類型:MODULE, PROTECTED, PACKAGE, PRIVATE
2.3 @NonNull
顧名思義,@NonNull 用于標(biāo)記類中不能允許為 null 的字段或者參數(shù)上,任何使用該字段的地方都生成空指針判斷代碼,若@NonNull 標(biāo)記的變量為 null,拋出 NullPointException (NPE) 異常。比如下面示例代碼:
public class User { private Integer id; private String username; private String password; public User(Integer id, @NonNull String username, @NonNull String password) { this.id = id; this.username = username; this.password = password; } }
使用了 @NonNull 注解之后我們可以獲取到反編譯之后的字節(jié)碼信息如下,這就是 Lombok 給我們生成的最終的代碼:
public class User { private Integer id; private String username; private String password; public User(Integer id, @NonNull String username, @NonNull String password) { if (username == null) { throw new NullPointerException("username is marked non-null but is null"); } else if (password == null) { throw new NullPointerException("password is marked non-null but is null"); } else { this.id = id; this.username = username; this.password = password; } } }
2.4 構(gòu)造器注解
再來看下平時(shí)經(jīng)常會(huì)遇見的場景,為實(shí)體類編寫構(gòu)造器方法,Lombok 提供了三個(gè)不同構(gòu)造器注解 @NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor 分別對用不同構(gòu)造器方法處理方式,接下來就一一描述。
@NoArgsConstructor 為實(shí)體類生成無參的構(gòu)造器方法
@AllArgsConstructor 為實(shí)體類生成除了static修飾的字段之外帶有各參數(shù)的構(gòu)造器方法。
@RequiredArgsConstructor 為實(shí)體類生成指定字段的構(gòu)造器方法,而這些字段需要被 final,或者 @NonNull 修飾。
```java @RequiredArgsConstructor public class User3 { private Integer id; private final String username; @NonNull private String password; } ```
編譯成功后使用構(gòu)造器方法時(shí)就是這樣的效果:User3 user3 = new User3("user3", "zxc123");
2.5 @ToString
@ToString 會(huì)給類自動(dòng)生成易閱讀的 toString 方法,帶上有所非靜態(tài)字段的屬性名稱和值,這樣就十分便于我們?nèi)粘i_發(fā)時(shí)進(jìn)行的打印操作。
@Getter
@Setter
@AllArgsConstructor
@ToString
public class User2 {
private Integer id;
private String username;
private String password;
}
最終編譯成字節(jié)碼,反編譯結(jié)果如下:
public class User2 { private Integer id; private String username; private String password; // 省去 setter/getter public String toString() { return "User2(id=" + this.getId() + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ")"; } }
另外,注解 @ToString 還支持設(shè)置指定哪些字段的日志化輸出,哪些不需要出現(xiàn)在 toString 方法中。使用屬性 @ToString.Exclude排除不需要在 toString 中出現(xiàn)的字段,使用 @ToString.Include標(biāo)記需要出現(xiàn)在 toString 中的字段,具體用法可參見示例:
@Getter @Setter @AllArgsConstructor @ToString public class User2 { @ToString.Exclude private Integer id; @ToString.Include private String username; @ToString.Include private String password; }
打印 User2 對象的日志效果就是:User2(username=user2, password=zcx123)。
2.6 @EqualsAndHashCode
@EqualsAndHashCode 注解就是用于根據(jù)類所擁有的非靜態(tài)字段自動(dòng)重寫 equals 方法和 hashCode 方法,方便我們用于對象間的比較。類似 @ToString,@EqualsAndHashCode 還可以使用需要作為比較的字段和排除不需要比較的字段,具體用法可以看如下示例:
@Getter @Setter @AllArgsConstructor @ToString @EqualsAndHashCode public class User4 { @EqualsAndHashCode.Exclude private Integer id; @EqualsAndHashCode.Include private String username; @EqualsAndHashCode.Exclude private String password; }
寫完實(shí)體類代碼,我們編寫測試方法試下效果:
@Test public void testEqual() { User4 user4 = new User4(1, "user4", "zxc"); User4 user4_2 = new User4(1, "user4", "123"); Assert.assertEquals(user4, user4_2); // ture }
2.7 @Data/@Value
@Data/@Value 注解,提供了更綜合的生成代碼功能,等價(jià)于下面幾個(gè)注解
@Getter
@Setter
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
兩個(gè)注解都只能使用在類上,與 @Data 不同, @Value 用來修飾不可變的類上。一般實(shí)體類沒有特別的限制的話,通??梢灾苯邮褂?@Data 注解修飾。
2.8 @Builder
@Builder 是一個(gè)非常強(qiáng)大的注解,提供了一種基于建造者模式的構(gòu)建對象的 API。使用 @Builder 注解為給我們的實(shí)體類自動(dòng)生成 builder() 方法,并且直接根據(jù)字段名稱方法進(jìn)行字段賦值,最后使用 build()方法構(gòu)建出一個(gè)實(shí)體對象。
@Data @Builder public class User6 { private Integer id; private String username; private String password; } @Test public void testBuilder() { User6 user6 = User6.builder().id(1).username("user6").password("zxc123").build(); log.warn("testLog: {}", user6); // User6(id=1, username=user6, password=zxc123) }
需要注意的是 @Builder 不支持父類字段的生成,當(dāng)一個(gè)實(shí)體類存在父類時(shí),@Builder 只能生成當(dāng)前類的字段構(gòu)建方法。
若需要用到父類的字段方法時(shí), Lombok 提供了新的注解 @SuperBuilder 來應(yīng)對這種情況,下面是 @SuperBuilder 注解的使用方式:
@SuperBuilder @Getter @Setter public class Parent { private int id; private String name; } @SuperBuilder @Data public class Child extends Parent { private String childName; }
調(diào)用示例:
Child child = Child.builder().id(1).name("父類名稱").childName("子類名稱").build(); System.out.println(child.getId());
由于 Lombok Plugin 還未更新支持@SuperBuilder,所以以上寫法在 IDEA 下還會(huì)提示編譯錯(cuò)誤,無法找到 builder()方法。
也可以參考此文方式去處理繼承的情況:reinhard.codes/2015/09/16/…
2.9 日志注解
正對程序類中常見不同框架 Logger 對象,Lombok 也提供了注解,來自動(dòng)生成 Logger 對象,實(shí)現(xiàn)優(yōu)雅地輸出日志,只需要在類上使用日志注解如 @Log。當(dāng)然 Lombok 支持了多個(gè)日志框架,并且提供對應(yīng)的注解如下:
@CommonsLog 等價(jià)效果: private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@Flogger 等價(jià)效果: private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
@JBosLog 等價(jià)效果: private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log 等價(jià)效果: private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j 等價(jià)效果: private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2 等價(jià)效果: private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j 等價(jià)效果: private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j 等價(jià)效果: private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
下面代碼使用 @Slf4j 注解進(jìn)行日志輸出:
@Slf4j public class UserTests { // .... @Test public void testLog() { User5 user5 = new User5(); user5.setId(1); user5.setUsername("user5"); user5.setPassword("zxc123"); log.warn("testLog: {}", user5); // 21:57:15.488 [main] WARN com.one.learn.lombok.UserTests - testLog: User5(id=1, username=user5, password=zxc123) } }
2.10 @Cleanup
@Cleanup 用于標(biāo)記需要釋放清理操作的資源對象變量,如 FileInputStream, FileOutputStream 等,標(biāo)記之后資源對象使用完畢后,就會(huì)被自動(dòng)關(guān)閉和清理,實(shí)際上這里 Lombok 實(shí)現(xiàn)效果與 Java7 特性 try with resource 一樣, 為我們屏蔽了關(guān)閉資源的模板代碼,下面給出 @Cleanup 的使用示例:
public class CleanupExample { public static void main(String[] args) throws IOException { @Cleanup InputStream in = new FileInputStream(args[0]); @Cleanup OutputStream out = new FileOutputStream(args[1]); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) { break; } out.write(b, 0, r); } } }
將 CleanupExample.java 編譯生成的字節(jié)碼反編譯可以得到如下結(jié)果:
public class CleanupExample { //... public static void main(String[] args) throws IOException { FileInputStream in = new FileInputStream(args[0]); try { FileOutputStream out = new FileOutputStream(args[1]); try { byte[] b = new byte[10000]; while(true) { int r = in.read(b); if (r == -1) { return; } out.write(b, 0, r); } } finally { if (Collections.singletonList(out).get(0) != null) { out.close(); } } } finally { if (Collections.singletonList(in).get(0) != null) { in.close(); } } } }
2.11 @SneakyThrows
@SneakyThrows 主要用于在沒有 throws 關(guān)鍵字的情況下,隱蔽地拋出受檢查異常,為我們平常開發(fā)中需要異常拋出時(shí)省去的 throw 操作,下面為使用 @SneakyThrows 的示例代碼:
public class SneakyThrowsExample implements Runnable { @SneakyThrows(UnsupportedEncodingException.class) public String utf8ToString(byte[] bytes) { return new String(bytes, "UTF-8"); } @SneakyThrows public void run() { throw new Throwable(); } }
最終編譯成字節(jié)碼,反編譯結(jié)果如下:
public class SneakyThrowsExample implements Runnable { public SneakyThrowsExample() { } public String utf8ToString(byte[] bytes) { try { return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException var3) { throw var3; } } public void run() { try { throw new Throwable(); } catch (Throwable var2) { throw var2; } } }
2.12 val/var
val/var 用于局部變量的修飾,有了這注解修飾后,變量的類型就會(huì)自動(dòng)通過等號右邊的表達(dá)式推斷出來,這個(gè)功能借鑒于許多編程語言的自動(dòng)類型推斷的特性。
而 val 與 var 的區(qū)別在于, val 用于修飾不可變變量,var 修飾可變變量。當(dāng) val 修飾的變量被重新賦值時(shí),編譯器就會(huì)提示異常:Error: java: 無法為最終變量 X 分配值。實(shí)際用法也比較簡單,可參考下面代碼:
@Slf4j public class VarValExample { public static void main(String[] args) { val text = "abc"; // text = "1"; // Error: java: 無法為最終變量 text 分配值`。 var num = 1; num = 2; log.info("text:{},num:{}", text, num); // text:abc,num:2 } }
看完上述內(nèi)容,你們掌握Lombok如何在Java項(xiàng)目中使用的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。