關(guān)于Lombok簡化編碼使用及說明
1.Lombok介紹以及其它簡介
1.1 介紹
Lombok是一個(gè)通過注解的形式或簡單關(guān)鍵字簡化和消除Java應(yīng)用程序中一些必須但是重復(fù)或顯得臃腫的樣板代碼的實(shí)用工具,使用Lombok會(huì)在編譯階段根據(jù)相應(yīng)的注解生成對應(yīng)的字節(jié)碼,使編譯前的源碼看起來更加簡潔,但功能不變。
其特征可參見官網(wǎng)
1.2 優(yōu)點(diǎn)
優(yōu)點(diǎn)有很多,這里主要列舉自己認(rèn)為重要的
- 提高編碼效率
- 使代碼更簡潔
- 消除冗長代碼
- 避免修改字段名字時(shí)忘記修改方法名
1.3 原理
1.為什么能使用Lombok?
Lombok支持JSR 269 Pluggable Annotation Processing API,Javac從Java6開始支持“JSR 269 API”規(guī)范,只要程序?qū)崿F(xiàn)了該API,就能在Javac運(yùn)行的時(shí)候得到調(diào)用
2.Javac編譯源碼的具體流程如下:
1.4 安裝
Lombok需要通過插件的形式與IDE集成,如果使用IntelliJ IDEA可直接到插件倉庫搜索Lombok進(jìn)行安裝,最后重啟IDEA。
如圖:
1.5 類構(gòu)造
注解(位置TYPE)/屬性 | staticName私有化生產(chǎn)的構(gòu)造器并生成一個(gè)靜態(tài)構(gòu)造方法 | onConstructor在生成的構(gòu)造器上增加其他注解 | access設(shè)置生成的構(gòu)造器的可見性 | force為true時(shí),初始化所有靜態(tài)屬性到0/false/null |
---|---|---|---|---|
@AllArgsConstructor生成一個(gè)全參構(gòu)造器 | √ | √ | √ | |
@RequiredArgsConstructor生成一個(gè)必要參數(shù)構(gòu)造器 | √ | √ | √ | |
@NoArgsConstructor生成一個(gè)空參構(gòu)造器 | √ | √ | √ | √ |
注解(位置) | 屬性 |
---|---|
@Builder(TYPE,METHOD, CONSTRUCTOR)生成目標(biāo)類的一個(gè)建造者內(nèi)部類 | builderClassName:自定義建造類 (TypeName)Builder 的類名builderMethodName:自定義 builder() 的方法名buildMethodName:自定義 build() 的方法名toBuilder: |
@Builder.ObtainVia(FIELD,PARAMETER)注明一個(gè)參數(shù)或?qū)傩缘墨@取方式 | field:使用 this.field 賦值method:使用this.method() 賦值isStatic:使用 SelfType.method(this) 賦值,要求 mthod 是靜態(tài)的 |
@Builder.Default(FIELD)注明一個(gè)屬性有默認(rèn)值 | |
@Singular(FIELD,PARAMETER)允許為集合類型的屬性一項(xiàng)一項(xiàng)賦值 | value:單項(xiàng)賦值方法的方法名 |
1.6 類屬性
注解(位置) | 屬性 |
---|---|
@Getter(TYPE,FIELD)自動(dòng)生成標(biāo)準(zhǔn)的getter方法 | lazy:默認(rèn)false,不可用onMethod:在方法上增加其他注解value:設(shè)置方法的可見性 |
@Setter(TYPE,FIELD)自動(dòng)生成標(biāo)準(zhǔn)的setter方法 | onParam:在方法參數(shù)上增加其他注解onMethod:同@Getter.onMethodvalue:同@Getter.value |
@Data(TYPE)@Getter/@Setter,@ToString, @EqualsAndHashCode和@RequiredArgsConstructor 組合的便捷寫法 | staticConstructor:同@RequiredArgsConstructor.staticName |
@EqualsAndHashCode(TYPE)利用父類方法和相關(guān)屬性生成equals()和hashCode() | callSuper:在使用本類屬性前先使用父類方法計(jì)算doNotUseGetters:不使用getter方法exclude:計(jì)算時(shí)不使用這里羅列的屬性of:計(jì)算時(shí)使用這里羅列的屬性onParam:同@Setter.onParam |
@ToString(TYPE)利用父類方法和相關(guān)屬性生成 | callSuper:同@EqualsAndHashCode.callSuperdoNotUseGetters:同@EqualsAndHashCode.doNotUseGettersexclude:同@EqualsAndHashCode.excludeof:同@EqualsAndHashCode.ofincludeFieldNames:是否打印屬性名 |
1.7 日志
注解(位置) | 日志類類型 |
---|---|
@CommonsLog | org.apache.commons.logging.Log |
@Log | java.util.logging.Logger |
@JBossLog | org.jboss.logging.Logger |
@Log4j | org.apache.log4j.Logger |
@Log4j2 | org.apache.logging.log4j.Logger |
@Slf4j | org.slf4j.Logger |
@Slf4j2 | org.slf4j.ext.XLogger |
關(guān)于日志上的注解,重點(diǎn)應(yīng)該放在日志類型的選擇上。一般情況下優(yōu)先使用@Slf4j或@Slf4j2
1.8 雜項(xiàng)
注解(位置) | 日志類類型 |
---|---|
@NonNull(FIELD,METHOD,PARAMETER,LOCAL_VARIABLE)自動(dòng)生成引用空檢查代碼,為空時(shí)拋出空指針異常 | |
@SneakThrows(METHOD,CONSTRUCTOR)自動(dòng)生成代碼,拋出受檢異常 | value:需要向上拋出的異常類型 |
@Synchronized(METHOD)被標(biāo)注的方法使用生成的鎖對象(lock和Lock)而非默認(rèn)的(this和SlefType) | value:使用指定的屬性作為鎖對象 |
@Value(TYPE)便捷地轉(zhuǎn)化可變類到不可變 | staticConstructor:同@RequiredArgsConstructor.staticName |
@Cleanup(LOCAL_VARIABLE)生成自動(dòng)關(guān)閉資源的代碼 | value:使用指定的方法關(guān)閉資源,默認(rèn)使用close() |
- val 便捷地聲明final局部變量的類型(主要用于含有類型推斷的情況)
- var val的非final情況
除了上述提到的注解和類,在 lombok.experimental 中還包含一些處于實(shí)驗(yàn)階段中的注解(例如自動(dòng)生成代理方法的@Delegate等)和類,這里不再描述。
2. 使用Lombok
要在項(xiàng)目中使用Lombok,首先要在項(xiàng)目中引入lombok的依賴(使用Maven引入),重新編譯源代碼
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.20</version> <scope>provided</scope> </dependency>
可根據(jù)項(xiàng)目自行選擇jar包版本:下載地址
IDEA中使用Lombok的注意事項(xiàng):
- 項(xiàng)目中要使用Lombok不僅IDEA要支持(否則一堆錯(cuò)誤),項(xiàng)目中也要引入jar包
- 如果配置lombok.config文件,修改文件的屬性值后,并不會(huì)自動(dòng)重新編譯class文件,IDEA編輯器也不會(huì)自動(dòng)更新,所有每次修改配置文件后最后關(guān)閉java文件窗口重新打開,并且clean下項(xiàng)目
2.1 常用注解
注解/關(guān)鍵字 | 可使用位置 | 說明 |
---|---|---|
val | 局部變量 | 簡化局部變量聲明的類型 |
@NonNull | 字段、方法、入?yún)?、本地變?/td> | 生成檢查NullPointException代碼 |
@Cleanup | 可關(guān)閉資源的本地變量對象,且銷毀方法沒有參數(shù) | 簡化資源清理回收的代碼,消除try-catch-finally代碼塊 |
@Getter / @Setter | 字段、枚舉常量、接口、類、枚舉、注解 | 簡化getter、setter代碼 |
@ToString | 接口、類、枚舉、注解 | 自動(dòng)生成toString方法(可以添加排除和依賴) |
@EqualsAndHashCode | 接口、類、枚舉、注解 | 自動(dòng)生成equals方法和hashCode方法 |
@NoArgsConstructor | 接口、類、枚舉、注解 | 生成無參構(gòu)造函數(shù) |
@RequiredArgsConstructo | 接口、類、枚舉、注解 | 生成所有標(biāo)識為@NonNull的成員屬性的構(gòu)造函數(shù) |
@AllArgsConstructor | 接口、類、枚舉、注解 | 生成包含所有成員屬性的構(gòu)造函數(shù) |
@Data | 接口、類、枚舉、注解 | 是@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstructor的組合效果 |
@Value | 接口、類、枚舉、注解 | 類似于@Data,區(qū)別在于字段會(huì)轉(zhuǎn)換為final類型,且沒有setter方法 |
@NonFinal | 字段、方法、方法參數(shù)、本地變量、注解、接口、類、枚舉 | 用來取消因使用@FieldDefaults和@Value而加上的final修飾符 |
@SneakyThrows | 方法、構(gòu)造函數(shù) | 粗粒度的try-catch,等同于try-catch 捕獲異常 |
@Synchronized | 方法 | 作用等同于synchronized關(guān)鍵字,可自定義鎖對象 |
@Log4j / @Slf4j / @Log | 接口、類、枚舉、注解 | 簡化定義日志記錄器對象的代碼,根據(jù)日志框架的不同選擇不同的Log注解 |
@Tolerate | 方法、注解 | 解決某些情況下使用Lombok注解生成的構(gòu)造器或方法與開發(fā)者自己寫構(gòu)造器或方法因?yàn)闆_突而被跳過的情況 |
@Builder | 類 | 會(huì)按builder模式生成一個(gè)內(nèi)部類 |
2.1.1 val / var
val用來簡化局部變量聲明的類型,與Java10中的var關(guān)鍵字類似,都是從初始化表達(dá)式中推斷出變量的聲明類型,起到本地類型推斷的作用。需要注意的是val修飾的變量都會(huì)變成final類型,其引用不可更改。
val example = new ArrayList<String>(); example.add("hello"); example.add("lombok"); val element = example.get(0);
等價(jià)于:
final ArrayList<String> example = new ArrayList<String>(); example.add("hello"); example.add("lombok"); final String element = example.get(0);
注意:
- 1.只能在本地變量聲明的時(shí)候使用,不可在類的字段上使用
- 2.val修飾的變量本身是final類型的,不能被修改
var與val關(guān)鍵字類似,同樣起到本地類型推斷的作用,區(qū)別在于var修飾的變量不會(huì)轉(zhuǎn)變?yōu)閒inal類型,而val修飾的變量都會(huì)變成final類型
2.1.2 @NonNull
常用于加在方法和構(gòu)造函數(shù)的入?yún)⑸?,它?huì)幫助我們生成檢查NullPointerException的代碼
public NonNullExample(@NonNull Person person) { this.name = person.getName(); }
等價(jià)于:
public NonNullExample(@NonNull Person person) { if(person == null) { throw new NullPointException("person"); } this.name = person.getName(); }
2.1.3 @Cleanup
用來簡化資源清理回收的代碼,確保指定的資源在退出當(dāng)前代碼執(zhí)行范圍前進(jìn)行自動(dòng)清理,消除常見的try-catch-finally代碼樣板,作用等同于try-with-resource,不過需要注意@Cleanup只能指定沒有參數(shù)的資源銷毀方法,如果銷毀方法有入?yún)t不能使用@Cleanup注解
public static void tradition() { InputStream in = null; OutputStream out = null; try { in = new FileInputStream("test.txt"); out = new FileOutputStream("output.txt"); byte[] buffer = new byte[1024]; int begin = 0; while (true) { int len = in.read(buffer); if (len == -1) break; out.write(buffer, begin, len); begin += len; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void tryWithResource() { try (InputStream in = new FileInputStream("test.txt"); OutputStream out = new FileOutputStream("output.txt")) { byte[] buffer = new byte[1024]; int begin = 0; while (true) { int len = in.read(buffer); if (len == -1) break; out.write(buffer, begin, len); begin += len; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void cleanUp() { try { @Cleanup InputStream in = new FileInputStream("test.txt"); @Cleanup OutputStream out = new FileOutputStream("output.txt"); byte[] buffer = new byte[1024]; int begin = 0; while (true) { int len = in.read(buffer); if (len == -1) break; out.write(buffer, begin, len); begin += len; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
2.1.4 @Getter / @Setter
分別用來簡化getter和setter樣板代碼,默認(rèn)生成的getter、setter方法修飾符為public,如果需要指定方法的訪問范圍,可以設(shè)置AccessLevel屬性,如:
@Getter @Setter(AccessLevel.PROTECTED) private String password;
另外,@Getter注解還有一個(gè)lazy=true的屬性,設(shè)置了該屬性會(huì)使我們調(diào)用getter方法時(shí)才真正去計(jì)算獲取到的值,并且將第一次計(jì)算后的結(jié)果緩存下來,之后的調(diào)用直接返回該緩存值
@Getter(lazy = true) private final double[] cached = expensive(); private double[] expensive() { long begin = System.currentTimeMillis(); double[] result = new double[5]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println((System.currentTimeMillis() - begin) / 1000); return result; } public static void main(String[] args) { GetterLazyExample example = new GetterLazyExample(); System.out.println(example.getCached()); System.out.println(example.getCached()); }
等價(jià)于:
private final AtomicReference<Object> cached = new AtomicReference<>(); public double[] getCached() { Object value = this.cached.get(); if (value == null) { synchronized (this.cached) { value = this.cached.get(); if (value == null) { final double[] actualValue = expensive(); value = actualValue == null ? this.cached : actualValue; this.cached.set(value); } } } return (double[]) (value == this.cached ? null : value); } private double[] expensive() { long begin = System.currentTimeMillis(); double[] result = new double[5]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println((System.currentTimeMillis() - begin) / 1000); return result; } public static void main(String[] args) { GetterLazyExample_Src example = new GetterLazyExample_Src(); System.out.println(example.getCached()); System.out.println(example.getCached()); }
2.1.5 @ToString
用來自動(dòng)生成toString方法,默認(rèn)的toString方法會(huì)打印出類名和字段屬性和值,如果需要排除指定字段可以用exclude='字段名’的方式進(jìn)行排除;如果要嵌套調(diào)用父類的toString方法,則加上callSuper=true,includeFieldNames=true等屬性
// @ToString // 默認(rèn)打印類名、每個(gè)字段名=值,用逗號分隔 // @ToString(exclude="password") //exclude屬性指定排除哪些字段 @ToString(callSuper = true,includeFieldNames=true) public class ToStringExample extends Parent { @Getter @Setter private String name; @Getter @Setter private String password; @Getter @Setter private int age; public static void main(String[] args) { System.out.println(new ToStringExample()); } } @ToString class Parent { @Getter @Setter private String address; @Getter @Setter private String city; }
2.1.6 @EqualsAndHashCode
用來從字段中自動(dòng)生成equals和hashCode方法,默認(rèn)情況下使用的是所有非靜態(tài)字段,也可以使用exclude屬性排除指定的字段
@EqualsAndHashCode(exclude= {"name"}) public class EqualsAndHashCodeExample { @Getter @Setter private String name; @Getter @Setter private int age; @Getter @Setter private double weight; public static void main(String[] args) { EqualsAndHashCodeExample example1 = new EqualsAndHashCodeExample(); example1.setName("小明"); example1.setAge(10); EqualsAndHashCodeExample example2 = new EqualsAndHashCodeExample(); example2.setName("小紅"); example2.setAge(10); System.out.println(example1.hashCode()); System.out.println(example2.hashCode()); System.out.println(example1.equals(example2)); } }
2.1.6 @NoArgsConstructor
用來生成無參構(gòu)造函數(shù),如果類含有final字段,會(huì)出現(xiàn)編譯錯(cuò)誤,通過指定屬性force為true,為final字段進(jìn)行初始化
@NoArgsConstructor public class NoArgsConstructorExample { @Getter @Setter private String name; }
等價(jià)于:
public class NoArgsConstructorExample { private String name; public NoArgsConstructorExample() { //public無參構(gòu)造器 } //省略getter、setter方法 ...... }
2.1.7 @RequiredArgsConstructor
用來生成包含所有修飾為@NonNull的成員屬性的構(gòu)造函數(shù)
@RequiredArgsConstructor public class RequiredArgsConstructorExample { @Getter @Setter @NonNull private String name; @Getter @Setter private String password; @Getter @Setter @NonNull private Character sex; }
等價(jià)于:
public class RequiredArgsConstructorExample { private String name; private String password; private Character sex; private RequiredArgsConstructorExample(String name, Character sex) { if(name == null) { throw new NullPointerException("name"); } if(sex == null) { throw new NullPointerException("sex"); } this.name = name; this.sex = sex; } //省略getter、setter方法 ...... }
2.1.8 @AllArgsConstructor
@AllArgsConstructor public class AllArgsContructorExample { @Getter @Setter private String name; @Getter @Setter private Integer age; @Getter @Setter private String address; }
等價(jià)于:
public class AllArgsContructorExample { private String name; private Integer age; private String address; public AllArgsContructorExample(String name, Integer age, String address) { this.name = name, this.age = age; this.address = address; } //省略getter、setter方法 ...... }
2.1.9 @Data
是一個(gè)簡單粗暴的組合注解,使用@Data注解相當(dāng)于同時(shí)使用了@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstructor這幾個(gè)注解
@Data public class DataExample { private String name; private int age; private String password; }
2.1.10 @Value
跟@Data類似,區(qū)別在于如果變量不加@NonFinal修飾,@Value會(huì)將字段變成final類型,同時(shí)也沒有setter方法
2.1.11 @NonFinal
修飾字段,用來取消因使用@FieldDefaults和@Value而加上的final修飾符
@Value public class NonFinalExample { private String id; //final private String name; //final @NonFinal private String password; //非final }
2.1.12 @Builder
簡化了普通的建造者模式API,可以用在類、構(gòu)造器、方法上,如果字段屬于集合類型,加上@Singular,會(huì)生成兩個(gè)向集合中添加單一元素和所有元素的方法,以及一個(gè)清除集合的方法
@Builder public class Example { private int foo; private final String bar; }
等價(jià)于:
public class Example<T> { private T foo; private final String bar; private Example(T foo, String bar) { this.foo = foo; this.bar = bar; } public static <T> ExampleBuilder<T> builder() { return new ExampleBuilder<T>(); } public static class ExampleBuilder<T> { private T foo; private String bar; private ExampleBuilder() {} public ExampleBuilder foo(T foo) { this.foo = foo; return this; } public ExampleBuilder bar(String bar) { this.bar = bar; return this; } @java.lang.Override public String toString() { return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")"; } public Example build() { return new Example(foo, bar); } } }
2.1.13 @SneakyThrows
注解用在方法和構(gòu)造函數(shù)上,它會(huì)將方法中的所有代碼用try-catch語句包裹起來,當(dāng)捕獲到異常后通過Lombok.sneakyThrow(e)將原始異常拋出,不過需要注意的是調(diào)用該方法的Client端并不知道會(huì)拋出哪種異常,即使這是一個(gè)CheckException
public class SneakyThrowsExample { @SneakyThrows(UnsupportedEncodingException.class) public static String utf8ToString(byte[] bytes) { return new String(bytes, "UTF-8"); } public static void main(String[] args) { String str = SneakyThrowsExample.utf8ToString("hello lomboks".getBytes()); System.out.println(str); } }
2.1.14 @Synchronized
注解用在方法上,作用等同于synchronized關(guān)鍵字,區(qū)別在于鎖對象不同,對于synchronized關(guān)鍵字,修飾類方法時(shí)鎖對象是class對象,修飾成員方法時(shí)鎖對象是this對象,而使用@synchronized注解時(shí)鎖對象分別是私有靜態(tài)變量LOCK和私有final對象lock,也可以自己指定鎖對象
public class SynchronizedExample { private final Object readLock = new Object(); @Synchronized("readLock") @SneakyThrows public void read() { System.out.println(Thread.currentThread().getName() + " read"); Thread.sleep(3000); } public static void main(String[] args) { SynchronizedExample example = new SynchronizedExample(); new Thread(()->example.read()).start(); new Thread(()->example.read()).start(); } }
2.1.15 Log注解:@CommonsLog、@Log、@Log4j、@Log4j2、@Slf4j、@XSl4j、@JBossLog
Log注解可以省去從日志工廠生成日志記錄器對象的代碼,可以使用topic指定生成log對象時(shí)的類名,根據(jù)項(xiàng)目中使用的日志框架不同,有不同的注解可以選擇
@CommonsLog(topic="LogExample") //等價(jià)于 org.apache.commons.logging.LogFactory.getLog(LogExample.class); @Log(topic="LogExample") //等價(jià)于 java.util.loggin.Logger.getLogger(LogExample.class); @Log4j(topic="LogExample") //等價(jià)于 org.apache.log4j.Logger.getLogger(LogExample.class); @Log4j2(topic="LogExample") //等價(jià)于 org.apache.loggin.log4j.LogManager.getLoggerr(LogExample.class); @Slf4j(topic="LogExample") //等價(jià)于 org.slf4j.LoggerFactory.getLogger(LogExample.class); @XSLf4j(topic="LogExample") //等價(jià)于 org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class); @JBossLog(topic="LogExample") //等價(jià)于 org.jboss.logging.Logger.getLogger(LogExample.class);
2.1.16 @Tolerate
該注解用來解決某些情況下使用Lombok注解生成的構(gòu)造器或方法與開發(fā)者自己寫構(gòu)造器或方法因?yàn)闆_突而被跳過的情況,將@Tolerate修飾在構(gòu)造器/方法上,會(huì)被lombok視為該構(gòu)造器/方法不存在,典型的如當(dāng)@Data和@Builder同時(shí)使用時(shí)Lombok生成構(gòu)造器只有一個(gè)包含所有成員屬性的構(gòu)造函數(shù),如果再自定義一個(gè)無參構(gòu)造函數(shù)將會(huì)沖突,此時(shí)可以使用@Tolerate解決
@Data @Builder public class TolerateExample { private String name; private String age; @Tolerate public TolerateExample() { } }
2.1.17 @UtilityClass
創(chuàng)建工具類的注釋,當(dāng)在類上加上該注解,該類會(huì)被修飾為final類型,如果該類聲明了構(gòu)造函數(shù)編譯器將會(huì)提示錯(cuò)誤,否則會(huì)自動(dòng)生成一個(gè)私有的構(gòu)造函數(shù),內(nèi)部拋出一個(gè)UnsupportedOperationException異常。并且所有的方法、內(nèi)部類和屬性都會(huì)被修飾為static
@UtilityClass public class UtilityClassExample { private DateFormat df = new SimpleDateFormat("YYYY-MM-DD"); public String formateToDay(Date date) { return df.format(date); } }
等價(jià)于:
public class UtilityClassExample { private static DateFormat df = new SimpleDateFormat("YYYY-MM-DD"); public static String formateToDay(Date date) { return df.format(date); } private UtilityClassExample() { throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } }
除了以上常用的基本功能外,Lombok還有部分實(shí)驗(yàn)性質(zhì)的特性沒有正式推薦使用,有些可能違背了對Java的常規(guī)認(rèn)知或者只支持部分開發(fā)環(huán)境,所以不推薦使用
2.2 擴(kuò)展
2.2.1 lombok.config增加
lombok.equalsAndHashCode.doNotUseGetters = [true | false] (default:false)
如果設(shè)置為 true,lombok將直接訪問字段,而不是在生成equals和hashcode方法時(shí)使用getter(如果可用),可以在該注解上配置屬性 donotusegetter 來標(biāo)示不使用getter的字段,這樣可以覆蓋默認(rèn)配置
lombok.equalsAndHashCode.callSuper = [call | skip | warn] (default:warn)
如果設(shè)置為 call,lombok將生成對hashCode的超類實(shí)現(xiàn)的調(diào)用
如果設(shè)置為 skip,則不會(huì)生成這樣的調(diào)用,默認(rèn)行為 warn 類似于 skip,并帶有附加警告。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
淺談Springboot下引入mybatis遇到的坑點(diǎn)
這篇文章主要介紹了Springboot下引入mybatis遇到的坑點(diǎn),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08idea中一鍵自動(dòng)生成序列化serialVersionUID方式
這篇文章主要介紹了idea中一鍵自動(dòng)生成序列化serialVersionUID方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09Spring Boot項(xiàng)目添加外部Jar包以及配置多數(shù)據(jù)源的完整步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot項(xiàng)目添加外部Jar包以及配置多數(shù)據(jù)源的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06使用idea開發(fā)javaWeb應(yīng)用程序的思路(實(shí)現(xiàn)用戶的增刪改查)
這篇文章主要介紹了使用idea開發(fā)javaWeb應(yīng)用程序的思路(實(shí)現(xiàn)用戶的增刪改查),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01Java打印出所有的水仙花數(shù)的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java打印出所有的水仙花數(shù)的實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-02-02