日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java: 程序包lombok不存在_Java开发神器:Lombok 学习指南

發(fā)布時間:2023/12/1 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java: 程序包lombok不存在_Java开发神器:Lombok 学习指南 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊上方“Java知音”,選擇“置頂公眾號”

技術(shù)文章第一時間送達!

作者:semlinker

www.segmentfault.com/a/1190000020864572

一、Lombok 簡介

Lombok 是一款 Java 開發(fā)插件,使得 Java 開發(fā)者可以通過其定義的一些注解來消除業(yè)務(wù)工程中冗長和繁瑣的代碼,尤其對于簡單的 Java 模型對象(POJO)。

在開發(fā)環(huán)境中使用 Lombok 插件后,Java 開發(fā)人員可以節(jié)省出重復構(gòu)建,諸如 hashCode 和 equals 這樣的方法以及各種業(yè)務(wù)對象模型的 accessor 和 toString 等方法的大量時間。

對于這些方法,Lombok 能夠在編譯源代碼期間自動幫我們生成這些方法,但并不會像反射那樣降低程序的性能。

二、Lombok 安裝

2.1 構(gòu)建工具

Gradle

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

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

Maven

在 Maven 項目的 pom.xml 文件中添加 lombok 依賴:

<dependency>
????????<groupId>org.projectlombokgroupId>
????????<artifactId>lombokartifactId>
????????<version>1.18.10version>
????????<scope>providedscope>
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>

2.2 IDE

由于 Lombok 僅在編譯階段生成代碼,所以使用 Lombok 注解的源代碼,在 IDE 中會被高亮顯示錯誤,針對這個問題可以通過安裝 IDE 對應(yīng)的插件來解決。

這里不詳細展開,具體的安裝方式可以參考:

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

三、Lombok 詳解

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

3.1 @Getter and @Setter 注解

你可以使用 @Getter 或 @Setter 注釋任何類或字段,Lombok 會自動生成默認的 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?{};
}

使用示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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 注解支持一個 lazy 屬性,該屬性默認為 false。當設(shè)置為 true 時,會啟用延遲初始化,即當首次調(diào)用 getter 方法時才進行初始化。

示例

package?com.semlinker.lombok;

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 編譯后,會生成如下代碼:

package?com.semlinker.lombok;

public?class?LazyGetterDemo?{
????private?final?String?notLazy?=?this.createValue("not?lazy");
????private?final?AtomicReference?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 方法時,若發(fā)現(xiàn) value 為 null,則會在同步代碼塊中執(zhí)行初始化操作。

3.2 Constructor Annotations

@NoArgsConstructor 注解

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

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

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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òu)造函數(shù)且生成一個staticName指定的靜態(tài)方法
????String?staticName()?default?"";
????AnyAnnotation[]?onConstructor()?default?{};
??//?設(shè)置生成構(gòu)造函數(shù)的訪問級別,默認是public
????AccessLevel?access()?default?lombok.AccessLevel.PUBLIC;
}

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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;
????}
}

@RequiredArgsConstructorDemo 注解

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

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

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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?{};

??//?標識在執(zhí)行字段計算前,是否調(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?"";
????}
}

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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?{
??//?打印輸出時是否包含字段的名稱
????boolean?includeFieldNames()?default?true;

??//?列出打印輸出時,需要排除的字段列表
????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?"";
????}
}

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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 注解與同時使用以下的注解的效果是一樣的:

  • @ToString

  • @Getter

  • @Setter

  • @RequiredArgsConstructor

  • @EqualsAndHashCode

@Data 注解的定義如下:

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

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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)的任何一種);之后,你將擁有一個靜態(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)和實例方法上。它的操作類似于 synchronized 關(guān)鍵字,但是它鎖定在不同的對象上。synchronized 關(guān)鍵字應(yīng)用在實例方法時,鎖定的是 this 對象,而應(yīng)用在靜態(tài)方法上鎖定的是類對象。

對于 @Synchronized 注解聲明的方法來說,它鎖定的是?$LOCK?或?$lock。@Synchronized 注解的定義如下:

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

示例

package?com.semlinker.lombok;

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 編譯后,會生成如下代碼:

package?com.semlinker.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 注解可以為指定類實現(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實例的方法名稱
????String?builderMethodName()?default?"builder";
????//?創(chuàng)建Builder注解類對應(yīng)實例的方法名稱
????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;
????}
}

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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 注解用于自動拋出已檢查的異常,而無需在方法中使用 throw 語句顯式拋出。@SneakyThrows 注解的定義如下:

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

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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 注解,它將會為你自動生成非空校驗語句。@NonNull 注解的定義如下:

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

示例

package?com.semlinker.lombok;

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

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

package?com.semlinker.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 注解用于自動管理資源,用在局部變量之前,在當前變量范圍內(nèi)即將執(zhí)行完畢退出之前會自動清理資源,自動生成 try-finally 這樣的代碼來關(guān)閉流。

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

示例

package?com.semlinker.lombok;

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 編譯后,會生成如下代碼:

package?com.semlinker.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 注解之后,將會自動生成一個 withFieldName(newValue) 的方法,該方法會基于 newValue 調(diào)用相應(yīng)構(gòu)造函數(shù),創(chuàng)建一個當前類對應(yīng)的實例。@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 用在局部變量前面,相當于將變量聲明為 final,此外 Lombok 在編譯時還會自動進行類型推斷。val 的使用示例:

public?class?ValExample?{
??public?String?example()?{
????val?example?=?new?ArrayList();
????example.add("Hello,?World!");
????val?foo?=?example.get(0);return?foo.toLowerCase();
??}public?void?example2()?{
????val?map?=?new?HashMap();map.put(0,?"zero");map.put(5,?"five");for?(val?entry?:?map.entrySet())?{
??????System.out.printf("%d:?%s\n",?entry.getKey(),?entry.getValue());
????}
??}
}

以上代碼等價于:

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?HashMapString>?map?=?new?HashMapString>();
????map.put(0,?"zero");
????map.put(5,?"five");for?(final?Map.EntryString>?entry?:?map.entrySet())?{
??????System.out.printf("%d:?%s\n",?entry.getKey(),?entry.getValue());
????}
??}
}

至此功能強大的 Lombok 工具就介紹完了。若你對于它的實現(xiàn)原理感興趣的話,建議閱讀:

https://www.jianshu.com/p/63038c7c515a

示例項目地址:

https://github.com/semlinker/springstack/tree/master/springboot2-lombok

四、參考資源

  • https://projectlombok.org/

  • https://interviewbubble.com/lombok-cheatsheet/

  • http://blog.didispace.com/java-lombok-how-to-use/

END

Java面試題專欄

【01期】Spring,SpringMVC,SpringBoot,SpringCloud有什么區(qū)別和聯(lián)系?

【02期】你能說說Spring框架中Bean的生命周期嗎?

【03期】如何決定使用 HashMap 還是 TreeMap?

【04期】分庫分表之后,id 主鍵如何處理?

【05期】消息隊列中,如何保證消息的順序性?

【06期】單例模式有幾種寫法?

【07期】Redis中是如何實現(xiàn)分布式鎖的?

【08期】說說Object類下面有幾種方法呢?

【09期】說說hashCode() 和 equals() 之間的關(guān)系?

【10期】Redis 面試常見問答

我知道你 “在看

總結(jié)

以上是生活随笔為你收集整理的java: 程序包lombok不存在_Java开发神器:Lombok 学习指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。