<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Lombok 使用指南

          共 21052字,需瀏覽 43分鐘

           ·

          2021-05-27 04:15

          0x01:Lombok簡介

          Lombok 是一款 Java開發(fā)插件,使得 Java 開發(fā)者可以通過其定義的一些注解來消除業(yè)務(wù)工程中冗長和繁瑣的代碼,尤其對于簡單的 Java 模型對象(POJO)。在開發(fā)環(huán)境中使用 Lombok插件后,Java 開發(fā)人員可以節(jié)省出重復(fù)構(gòu)建,諸如 hashCode 和 equals 這樣的方法以及各種業(yè)務(wù)對象模型的 accessor 和 toString 等方法的大量時(shí)間。對于這些方法,Lombok 能夠在編譯源代碼期間自動(dòng)幫我們生成這些方法,但并不會像反射那樣降低程序的性能。


          0x02:Lombok安裝

          構(gòu)建工具

          • Gradle

          在 build.gradle 文件中添加 Lombok 依賴:

          dependencies?{
          ????compileOnly?'org.projectlombok:lombok:1.18.10'
          ????annotationProcessor?'org.projectlombok:lombok:1.18.10'
          }
          • Maven

          在 Maven 項(xiàng)目的 pom.xml 文件中添加 Lombok 依賴:

          <dependency>
          ????<groupId>org.projectlombok</groupId>
          ????<artifactId>lombok</artifactId>
          ????<version>1.18.10</version>
          ????<scope>provided</scope>
          </dependency>
          • Ant

          假設(shè)在 lib 目錄中已經(jīng)存在 lombok.jar,然后設(shè)置 javac 任務(wù):

          <javac?srcdir="src"?destdir="build"?source="1.8">
          ????<classpath?location="lib/lombok.jar"?/>
          </javac>

          IDE

          由于 Lombok 僅在編譯階段生成代碼,所以使用 Lombok 注解的源代碼,在 IDE 中會被高亮顯示錯(cuò)誤,針對這個(gè)問題可以通過安裝 IDE 對應(yīng)的插件來解決。這里不詳細(xì)展開,具體的安裝方式可以參考:

          https://www.baeldung.com/lombok-ide


          0x03:Lombok 詳解

          注意:以下示例所使用的 Lombok 版本是 1.18.10

          3.1 @Getter? and @Setter?

          你可以使用 @Getter 或 @Setter 注釋任何類或字段,Lombok 會自動(dòng)生成默認(rèn)的 getter/setter 方法。

          • @Getter? 注解?

          @Target({ElementType.FIELD,?ElementType.TYPE})
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?Getter?{
          ??//?若getter方法非public的話,可以設(shè)置可訪問級別
          ????lombok.AccessLevel?value()?default?lombok.AccessLevel.PUBLIC;
          ????AnyAnnotation[]?onMethod()?default?{};
          ??//?是否啟用延遲初始化
          ????boolean?lazy()?default?false;
          }
          • @Setter?

          @Target({ElementType.FIELD,?ElementType.TYPE})
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?Setter?{
          ??//?若setter方法非public的話,可以設(shè)置可訪問級別
          ????lombok.AccessLevel?value()?default?lombok.AccessLevel.PUBLIC;
          ????AnyAnnotation[]?onMethod()?default?{};
          ????AnyAnnotation[]?onParam()?default?{};
          }

          使用示例

          @Getter
          @Setter
          public?class?GetterAndSetterDemo?{
          ????String?firstName;
          ????String?lastName;
          ????LocalDate?dateOfBirth;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?GetterAndSetterDemo?{
          ????String?firstName;
          ????String?lastName;
          ????LocalDate?dateOfBirth;
          ????public?GetterAndSetterDemo()?{
          ????}
          ????//?省略其它setter和getter方法
          ????public?String?getFirstName()?{
          ????????return?this.firstName;
          ????}
          ????public?void?setFirstName(String?firstName)?{
          ????????this.firstName?=?firstName;
          ????}
          }
          • Lazy Getter

          @Getter ?注解支持一個(gè) lazy 屬性,該屬性默認(rèn)為 false。當(dāng)設(shè)置為 true 時(shí),會啟用延遲初始化,即當(dāng)首次調(diào)用 getter 方法時(shí)才進(jìn)行初始化。?

          示例

          public?class?LazyGetterDemo?{
          ????public?static?void?main(String[]?args)?{
          ????????LazyGetterDemo?m?=?new?LazyGetterDemo();
          ????????System.out.println("Main?instance?is?created");
          ????????m.getLazy();
          ????}
          ????@Getter
          ????private?final?String?notLazy?=?createValue("not?lazy");
          ????@Getter(lazy?=?true)
          ????private?final?String?lazy?=?createValue("lazy");
          ????private?String?createValue(String?name)?{
          ????????System.out.println("createValue("?+?name?+?")");
          ????????return?null;
          ????}
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?LazyGetterDemo?{
          ????private?final?String?notLazy?=?this.createValue("not?lazy");
          ????private?final?AtomicReference<Object>?lazy?=?new?AtomicReference();
          ????//?已省略部分代碼
          ????public?String?getNotLazy()?{
          ????????return?this.notLazy;
          ????}
          ????public?String?getLazy()?{
          ????????Object?value?=?this.lazy.get();
          ????????if?(value?==?null)?{
          ????????????synchronized(this.lazy)?{
          ????????????????value?=?this.lazy.get();
          ????????????????if?(value?==?null)?{
          ????????????????????String?actualValue?=?this.createValue("lazy");
          ????????????????????value?=?actualValue?==?null???this.lazy?:?actualValue;
          ????????????????????this.lazy.set(value);
          ????????????????}
          ????????????}
          ????????}
          ????????return?(String)((String)(value?==?this.lazy???null?:?value));
          ????}
          }

          通過以上代碼可知,調(diào)用 getLazy 方法時(shí),若發(fā)現(xiàn) value 為 null,則會在同步代碼塊中執(zhí)行初始化操作。

          3.2 Constructor Annotations

          • @NoArgsConstructor?

          使用 @NoArgsConstructor ?注解可以為指定類,生成默認(rèn)的構(gòu)造函數(shù),@NoArgsConstructor ?注解的定義如下:?

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?NoArgsConstructor?{
          ??//?若設(shè)置該屬性,將會生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
          ????String?staticName()?default?"";
          ????AnyAnnotation[]?onConstructor()?default?{};
          ??//?設(shè)置生成構(gòu)造函數(shù)的訪問級別,默認(rèn)是public
          ????AccessLevel?access()?default?lombok.AccessLevel.PUBLIC;
          ??//?若設(shè)置為true,則初始化所有final的字段為0/null/false
          ????boolean?force()?default?false;
          }

          示例

          @NoArgsConstructor(staticName?=?"getInstance")
          public?class?NoArgsConstructorDemo?{
          ????private?long?id;
          ????private?String?name;
          ????private?int?age;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?NoArgsConstructorDemo?{
          ????private?long?id;
          ????private?String?name;
          ????private?int?age;
          ????private?NoArgsConstructorDemo()?{
          ????}
          ????public?static?NoArgsConstructorDemo?getInstance()?{
          ????????return?new?NoArgsConstructorDemo();
          ????}
          }
          • @AllArgsConstructor?

          使用 @AllArgsConstructor ?注解可以為指定類,生成包含所有成員的構(gòu)造函數(shù),@AllArgsConstructor ?注解的定義如下:?

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?AllArgsConstructor?{
          ??//?若設(shè)置該屬性,將會生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
          ????String?staticName()?default?"";
          ????AnyAnnotation[]?onConstructor()?default?{};
          ??//?設(shè)置生成構(gòu)造函數(shù)的訪問級別,默認(rèn)是public
          ????AccessLevel?access()?default?lombok.AccessLevel.PUBLIC;
          }

          示例

          @AllArgsConstructor
          public?class?AllArgsConstructorDemo?{
          ????private?long?id;
          ????private?String?name;
          ????private?int?age;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?AllArgsConstructorDemo?{
          ????private?long?id;
          ????private?String?name;
          ????private?int?age;
          ????public?AllArgsConstructorDemo(long?id,?String?name,?int?age)?{
          ????????this.id?=?id;
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}
          }
          • @RequiredArgsConstructor

          使用 @RequiredArgsConstructor 注解可以為指定類必需初始化的成員變量,如 final 成員變量,生成對應(yīng)的構(gòu)造函數(shù),@RequiredArgsConstructor 注解的定義如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?RequiredArgsConstructor?{
          ??//?若設(shè)置該屬性,將會生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
          ????String?staticName()?default?"";
          ????AnyAnnotation[]?onConstructor()?default?{};
          ??//?設(shè)置生成構(gòu)造函數(shù)的訪問級別,默認(rèn)是public
          ????AccessLevel?access()?default?lombok.AccessLevel.PUBLIC;
          }

          示例

          @RequiredArgsConstructor
          public?class?RequiredArgsConstructorDemo?{
          ????private?final?long?id;
          ????private?String?name;
          ????private?int?age;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?RequiredArgsConstructorDemo?{
          ????private?final?long?id;
          ????private?String?name;
          ????private?int?age;
          ????public?RequiredArgsConstructorDemo(long?id)?{
          ????????this.id?=?id;
          ????}
          }

          3.3 @EqualsAndHashCode?

          使用 @EqualsAndHashCode ?注解可以為指定類生成 equals 和 hashCode 方法, @EqualsAndHashCode ?注解的定義如下:?

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?EqualsAndHashCode?{
          ??//?指定在生成的equals和hashCode方法中需要排除的字段列表
          ????String[]?exclude()?default?{};

          ??//?顯式列出用于identity的字段,一般情況下non-static,non-transient字段會被用于identity
          ????String[]?of()?default?{};

          ??//?標(biāo)識在執(zhí)行字段計(jì)算前,是否調(diào)用父類的equals和hashCode方法
          ????boolean?callSuper()?default?false;

          ????boolean?doNotUseGetters()?default?false;

          ????AnyAnnotation[]?onParam()?default?{};

          ????@Deprecated
          ????@Retention(RetentionPolicy.SOURCE)
          ????@Target({})
          ????@interface?AnyAnnotation?{}

          ????@Target(ElementType.FIELD)
          ????@Retention(RetentionPolicy.SOURCE)
          ????public?@interface?Exclude?{}

          ????@Target({ElementType.FIELD,?ElementType.METHOD})
          ????@Retention(RetentionPolicy.SOURCE)
          ????public?@interface?Include?{
          ????????String?replaces()?default?"";
          ????}
          }

          示例

          @EqualsAndHashCode
          public?class?EqualsAndHashCodeDemo?{
          ????String?firstName;
          ????String?lastName;
          ????LocalDate?dateOfBirth;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?EqualsAndHashCodeDemo?{
          ????String?firstName;
          ????String?lastName;
          ????LocalDate?dateOfBirth;
          ????public?EqualsAndHashCodeDemo()?{
          ????}
          ????public?boolean?equals(Object?o)?{
          ????????if?(o?==?this)?{
          ????????????return?true;
          ????????}?else?if?(!(o?instanceof?EqualsAndHashCodeDemo))?{
          ????????????return?false;
          ????????}?else?{
          ????????????EqualsAndHashCodeDemo?other?=?(EqualsAndHashCodeDemo)o;
          ????????????if?(!other.canEqual(this))?{
          ????????????????return?false;
          ????????????}?else?{
          ??????????????//?已省略大量代碼
          ????????}
          ????}
          ????public?int?hashCode()?{
          ????????int?PRIME?=?true;
          ????????int?result?=?1;
          ????????Object?$firstName?=?this.firstName;
          ????????int?result?=?result?*?59?+?($firstName?==?null???43?:?$firstName.hashCode());
          ????????Object?$lastName?=?this.lastName;
          ????????result?=?result?*?59?+?($lastName?==?null???43?:?$lastName.hashCode());
          ????????Object?$dateOfBirth?=?this.dateOfBirth;
          ????????result?=?result?*?59?+?($dateOfBirth?==?null???43?:?$dateOfBirth.hashCode());
          ????????return?result;
          ????}
          }

          3.4 @ToString?

          使用 @ToString ?注解可以為指定類生成 toString 方法, @ToString ?注解的定義如下:?

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?ToString?{
          ??//?打印輸出時(shí)是否包含字段的名稱
          ????boolean?includeFieldNames()?default?true;

          ??//?列出打印輸出時(shí),需要排除的字段列表
          ????String[]?exclude()?default?{};

          ??//?顯式的列出需要打印輸出的字段列表
          ????String[]?of()?default?{};

          ??//?打印輸出的結(jié)果中是否包含父類的toString方法的返回結(jié)果
          ????boolean?callSuper()?default?false;

          ????boolean?doNotUseGetters()?default?false;

          ????boolean?onlyExplicitlyIncluded()?default?false;

          ????@Target(ElementType.FIELD)
          ????@Retention(RetentionPolicy.SOURCE)
          ????public?@interface?Exclude?{}

          ????@Target({ElementType.FIELD,?ElementType.METHOD})
          ????@Retention(RetentionPolicy.SOURCE)
          ????public?@interface?Include?{
          ????????int?rank()?default?0;
          ????????String?name()?default?"";
          ????}
          }

          示例

          @ToString(exclude?=?{"dateOfBirth"})
          public?class?ToStringDemo?{
          ????String?firstName;
          ????String?lastName;
          ????LocalDate?dateOfBirth;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?ToStringDemo?{
          ????String?firstName;
          ????String?lastName;
          ????LocalDate?dateOfBirth;
          ????public?ToStringDemo()?{
          ????}
          ????public?String?toString()?{
          ????????return?"ToStringDemo(firstName="?+?this.firstName?+?",?lastName="?+
          ??????????this.lastName?+?")";
          ????}
          }

          3.5 @Data?

          @Data ?注解與同時(shí)使用以下的注解的效果是一樣的:?

          @ToString
          @Getter
          @Setter
          @RequiredArgsConstructor
          @EqualsAndHashCode

          @Data ?注解的定義如下:?

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?Data?{
          ????String?staticConstructor()?default?"";
          }

          示例

          @Data
          public?class?DataDemo?{
          ????private?Long?id;
          ????private?String?summary;
          ????private?String?description;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?DataDemo?{
          ????private?Long?id;
          ????private?String?summary;
          ????private?String?description;
          ????public?DataDemo()?{
          ????}
          ????//?省略summary和description成員屬性的setter和getter方法
          ????public?Long?getId()?{
          ????????return?this.id;
          ????}

          ????public?void?setId(Long?id)?{
          ????????this.id?=?id;
          ????}
          ????public?boolean?equals(Object?o)?{
          ????????if?(o?==?this)?{
          ????????????return?true;
          ????????}?else?if?(!(o?instanceof?DataDemo))?{
          ????????????return?false;
          ????????}?else?{
          ????????????DataDemo?other?=?(DataDemo)o;
          ????????????if?(!other.canEqual(this))?{
          ????????????????return?false;
          ????????????}?else?{
          ???????????????//?已省略大量代碼
          ????????????}
          ????????}
          ????}
          ????protected?boolean?canEqual(Object?other)?{
          ????????return?other?instanceof?DataDemo;
          ????}
          ????public?int?hashCode()?{
          ????????int?PRIME?=?true;
          ????????int?result?=?1;
          ????????Object?$id?=?this.getId();
          ????????int?result?=?result?*?59?+?($id?==?null???43?:?$id.hashCode());
          ????????Object?$summary?=?this.getSummary();
          ????????result?=?result?*?59?+?($summary?==?null???43?:?$summary.hashCode());
          ????????Object?$description?=?this.getDescription();
          ????????result?=?result?*?59?+?($description?==?null???43?:?$description.hashCode());
          ????????return?result;
          ????}
          ????public?String?toString()?{
          ????????return?"DataDemo(id="?+?this.getId()?+?",?summary="?+?this.getSummary()?+?",?description="?+?this.getDescription()?+?")";
          ????}
          }

          3.6 @Log?

          若你將 @Log ?的變體放在類上(適用于你所使用的日志記錄系統(tǒng)的任何一種);之后,你將擁有一個(gè)靜態(tài)的 final log 字段,然后你就可以使用該字段來輸出日志。?

          @Log
          private?static?final?java.util.logging.Logger?log?=?java.util.logging.Logger.getLogger(LogExample.class.getName());
          @Log4j
          private?static?final?org.apache.log4j.Logger?log?=?org.apache.log4j.Logger.getLogger(LogExample.class);
          @Log4j2
          private?static?final?org.apache.logging.log4j.Logger?log?=?org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
          @Slf4j
          private?static?final?org.slf4j.Logger?log?=?org.slf4j.LoggerFactory.getLogger(LogExample.class);
          @XSlf4j
          private?static?final?org.slf4j.ext.XLogger?log?=?org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
          @CommonsLog
          private?static?final?org.apache.commons.logging.Log?log?=?org.apache.commons.logging.LogFactory.getLog(LogExample.class);

          3.7 @Synchronized?

          @Synchronized ?是同步方法修飾符的更安全的變體。與 synchronized 一樣,該注解只能應(yīng)用在靜態(tài)和實(shí)例方法上。它的操作類似于 synchronized 關(guān)鍵字,但是它鎖定在不同的對象上。synchronized 關(guān)鍵字應(yīng)用在實(shí)例方法時(shí),鎖定的是 this 對象,而應(yīng)用在靜態(tài)方法上鎖定的是類對象。對于 @Synchronized ?注解聲明的方法來說,它鎖定的是 或lock。@Synchronized ?注解的定義如下:?

          @Target(ElementType.METHOD)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?Synchronized?{
          ??//?指定鎖定的字段名稱
          ????String?value()?default?"";
          }

          示例

          public?class?SynchronizedDemo?{
          ????private?final?Object?readLock?=?new?Object();
          ????@Synchronized
          ????public?static?void?hello()?{
          ????????System.out.println("world");
          ????}
          ????@Synchronized
          ????public?int?answerToLife()?{
          ????????return?42;
          ????}
          ????@Synchronized("readLock")
          ????public?void?foo()?{
          ????????System.out.println("bar");
          ????}
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?SynchronizedDemo?{
          ????private?static?final?Object?$LOCK?=?new?Object[0];
          ????private?final?Object?$lock?=?new?Object[0];
          ????private?final?Object?readLock?=?new?Object();
          ????public?SynchronizedDemo()?{
          ????}
          ????public?static?void?hello()?{
          ????????synchronized($LOCK)?{
          ????????????System.out.println("world");
          ????????}
          ????}
          ????public?int?answerToLife()?{
          ????????synchronized(this.$lock)?{
          ????????????return?42;
          ????????}
          ????}
          ????public?void?foo()?{
          ????????synchronized(this.readLock)?{
          ????????????System.out.println("bar");
          ????????}
          ????}
          }

          3.8 @Builder?

          使用 @Builder ?注解可以為指定類實(shí)現(xiàn)建造者模式,該注解可以放在類、構(gòu)造函數(shù)或方法上。@Builder ?注解的定義如下:?

          @Target({TYPE,?METHOD,?CONSTRUCTOR})
          @Retention(SOURCE)
          public?@interface?Builder?{
          ????@Target(FIELD)
          ????@Retention(SOURCE)
          ????public?@interface?Default?{}
          ??//?創(chuàng)建新的builder實(shí)例的方法名稱
          ????String?builderMethodName()?default?"builder";
          ????//?創(chuàng)建Builder注解類對應(yīng)實(shí)例的方法名稱
          ????String?buildMethodName()?default?"build";
          ????//?builder類的名稱
          ????String?builderClassName()?default?"";

          ????boolean?toBuilder()?default?false;

          ????AccessLevel?access()?default?lombok.AccessLevel.PUBLIC;

          ????@Target({FIELD,?PARAMETER})
          ????@Retention(SOURCE)
          ????public?@interface?ObtainVia?{
          ????????String?field()?default?"";
          ????????String?method()?default?"";
          ????????boolean?isStatic()?default?false;
          ????}
          }

          示例

          @Builder
          public?class?BuilderDemo?{
          ????private?final?String?firstname;
          ????private?final?String?lastname;
          ????private?final?String?email;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?BuilderDemo?{
          ????private?final?String?firstname;
          ????private?final?String?lastname;
          ????private?final?String?email;
          ????BuilderDemo(String?firstname,?String?lastname,?String?email)?{
          ????????this.firstname?=?firstname;
          ????????this.lastname?=?lastname;
          ????????this.email?=?email;
          ????}
          ????public?static?BuilderDemo.BuilderDemoBuilder?builder()?{
          ????????return?new?BuilderDemo.BuilderDemoBuilder();
          ????}
          ????public?static?class?BuilderDemoBuilder?{
          ????????private?String?firstname;
          ????????private?String?lastname;
          ????????private?String?email;
          ????????BuilderDemoBuilder()?{
          ????????}
          ????????public?BuilderDemo.BuilderDemoBuilder?firstname(String?firstname)?{
          ????????????this.firstname?=?firstname;
          ????????????return?this;
          ????????}
          ????????public?BuilderDemo.BuilderDemoBuilder?lastname(String?lastname)?{
          ????????????this.lastname?=?lastname;
          ????????????return?this;
          ????????}
          ????????public?BuilderDemo.BuilderDemoBuilder?email(String?email)?{
          ????????????this.email?=?email;
          ????????????return?this;
          ????????}
          ????????public?BuilderDemo?build()?{
          ????????????return?new?BuilderDemo(this.firstname,?this.lastname,?this.email);
          ????????}
          ????????public?String?toString()?{
          ????????????return?"BuilderDemo.BuilderDemoBuilder(firstname="?+?this.firstname?+?",?lastname="?+?this.lastname?+?",?email="?+?this.email?+?")";
          ????????}
          ????}
          }

          3.9 @SneakyThrows?

          @SneakyThrows ?注解用于自動(dòng)拋出已檢查的異常,而無需在方法中使用 throw 語句顯式拋出。@SneakyThrows ?注解的定義如下:?

          @Target({ElementType.METHOD,?ElementType.CONSTRUCTOR})
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?SneakyThrows?{
          ????//?設(shè)置你希望向上拋的異常類
          ????Class<??extends?Throwable>[]?value()?default?java.lang.Throwable.class;
          }

          示例

          public?class?SneakyThrowsDemo?{
          ????@SneakyThrows
          ????@Override
          ????protected?Object?clone()?{
          ????????return?super.clone();
          ????}
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?SneakyThrowsDemo?{
          ????public?SneakyThrowsDemo()?{
          ????}
          ????protected?Object?clone()?{
          ????????try?{
          ????????????return?super.clone();
          ????????}?catch?(Throwable?var2)?{
          ????????????throw?var2;
          ????????}
          ????}
          }

          3.10 @NonNull?

          你可以在方法或構(gòu)造函數(shù)的參數(shù)上使用 @NonNull ?注解,它將會為你自動(dòng)生成非空校驗(yàn)語句。@NonNull ?注解的定義如下:?

          @Target({ElementType.FIELD,?ElementType.METHOD,?ElementType.PARAMETER,?ElementType.LOCAL_VARIABLE,?ElementType.TYPE_USE})
          @Retention(RetentionPolicy.CLASS)
          @Documented
          public?@interface?NonNull?{
          }

          示例

          public?class?NonNullDemo?{
          ????@Getter
          ????@Setter
          ????@NonNull
          ????private?String?name;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?NonNullDemo?{
          ????@NonNull
          ????private?String?name;
          ????public?NonNullDemo()?{
          ????}
          ????@NonNull
          ????public?String?getName()?{
          ????????return?this.name;
          ????}
          ????public?void?setName(@NonNull?String?name)?{
          ????????if?(name?==?null)?{
          ????????????throw?new?NullPointerException("name?is?marked?non-null?but?is?null");
          ????????}?else?{
          ????????????this.name?=?name;
          ????????}
          ????}
          }

          3.11 @Clean?

          @Clean ?注解用于自動(dòng)管理資源,用在局部變量之前,在當(dāng)前變量范圍內(nèi)即將執(zhí)行完畢退出之前會自動(dòng)清理資源,自動(dòng)生成 try-finally 這樣的代碼來關(guān)閉流。?

          @Target(ElementType.LOCAL_VARIABLE)
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?Cleanup?{
          ??//?設(shè)置用于執(zhí)行資源清理/回收的方法名稱,對應(yīng)方法不能包含任何參數(shù),默認(rèn)名稱為close。
          ????String?value()?default?"close";
          }

          示例

          public?class?CleanupDemo?{
          ????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);
          ????????}
          ????}
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?CleanupDemo?{
          ????public?CleanupDemo()?{
          ????}
          ????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();
          ????????????}
          ????????}
          ????}
          }

          3.11 @With?

          在類的字段上應(yīng)用 @With ?注解之后,將會自動(dòng)生成一個(gè) withFieldName(newValue) 的方法,該方法會基于 newValue 調(diào)用相應(yīng)構(gòu)造函數(shù),創(chuàng)建一個(gè)當(dāng)前類對應(yīng)的實(shí)例。@With ?注解的定義如下:?

          @Target({ElementType.FIELD,?ElementType.TYPE})
          @Retention(RetentionPolicy.SOURCE)
          public?@interface?With?{
          ????AccessLevel?value()?default?AccessLevel.PUBLIC;
          ????With.AnyAnnotation[]?onMethod()?default?{};
          ????With.AnyAnnotation[]?onParam()?default?{};
          ????@Deprecated
          ????@Retention(RetentionPolicy.SOURCE)
          ????@Target({})
          ????public?@interface?AnyAnnotation?{
          ????}
          }

          示例

          public?class?WithDemo?{
          ????@With(AccessLevel.PROTECTED)
          ????@NonNull
          ????private?final?String?name;
          ????@With
          ????private?final?int?age;
          ????public?WithDemo(String?name,?int?age)?{
          ????????if?(name?==?null)?throw?new?NullPointerException();
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}
          }

          以上代碼經(jīng)過 Lombok 編譯后,會生成如下代碼:

          public?class?WithDemo?{
          ????@NonNull
          ????private?final?String?name;
          ????private?final?int?age;
          ????public?WithDemo(String?name,?int?age)?{
          ????????if?(name?==?null)?{
          ????????????throw?new?NullPointerException();
          ????????}?else?{
          ????????????this.name?=?name;
          ????????????this.age?=?age;
          ????????}
          ????}
          ????protected?WithDemo?withName(@NonNull?String?name)?{
          ????????if?(name?==?null)?{
          ????????????throw?new?NullPointerException("name?is?marked?non-null?but?is?null");
          ????????}?else?{
          ????????????return?this.name?==?name???this?:?new?WithDemo(name,?this.age);
          ????????}
          ????}
          ????public?WithDemo?withAge(int?age)?{
          ????????return?this.age?==?age???this?:?new?WithDemo(this.name,?age);
          ????}
          }

          3.12 其它特性

          • val

          val 用在局部變量前面,相當(dāng)于將變量聲明為 final,此外 Lombok 在編譯時(shí)還會自動(dòng)進(jìn)行類型推斷。val 的使用示例:

          public?class?ValExample?{
          ??public?String?example()?{
          ????val?example?=?new?ArrayList<String>();
          ????example.add("Hello,?World!");
          ????val?foo?=?example.get(0);
          ????return?foo.toLowerCase();
          ??}

          ??public?void?example2()?{
          ????val?map?=?new?HashMap<Integer,?String>();
          ????map.put(0,?"zero");
          ????map.put(5,?"five");
          ????for?(val?entry?:?map.entrySet())?{
          ??????System.out.printf("%d:?%s\n",?entry.getKey(),?entry.getValue());
          ????}
          ??}
          }

          以上代碼等價(jià)于:

          public?class?ValExample?{
          ??public?String?example()?{
          ????final?ArrayList<String>?example?=?new?ArrayList<String>();
          ????example.add("Hello,?World!");
          ????final?String?foo?=?example.get(0);
          ????return?foo.toLowerCase();
          ??}

          ??public?void?example2()?{
          ????final?HashMap<Integer,?String>?map?=?new?HashMap<Integer,?String>();
          ????map.put(0,?"zero");
          ????map.put(5,?"five");
          ????for?(final?Map.Entry<Integer,?String>?entry?:?map.entrySet())?{
          ??????System.out.printf("%d:?%s\n",?entry.getKey(),?entry.getValue());
          ????}
          ??}
          }

          至此功能強(qiáng)大的 Lombok 工具就介紹完畢了。

          source:https://www.yuque.com/fengzheng-fly67/zln9pu/hgu2wb

          b047722f269d7205ad6535ced745d0e8.webp

          喜歡,在看



          瀏覽 52
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久成人大香蕉 | 伊人大香蕉视频网站 | 澳门AV在线 | 日皮视频免费在线观看 | 天天曰,天天干 |