0x01:Lombok簡(jiǎn)介
Lombok 是一款 Java開(kāi)發(fā)插件,使得 Java 開(kāi)發(fā)者可以通過(guò)其定義的一些注解來(lái)消除業(yè)務(wù)工程中冗長(zhǎng)和繁瑣的代碼,尤其對(duì)于簡(jiǎn)單的 Java 模型對(duì)象(POJO)。在開(kāi)發(fā)環(huán)境中使用 Lombok插件后,Java 開(kāi)發(fā)人員可以節(jié)省出重復(fù)構(gòu)建,諸如 hashCode 和 equals 這樣的方法以及各種業(yè)務(wù)對(duì)象模型的 accessor 和 toString 等方法的大量時(shí)間。對(duì)于這些方法,Lombok 能夠在編譯源代碼期間自動(dòng)幫我們生成這些方法,但并不會(huì)像反射那樣降低程序的性能。
0x02:Lombok安裝
構(gòu)建工具
Gradle
在 build.gradle 文件中添加 Lombok 依賴:
dependencies {
compileOnly ‘org.projectlombok1.18.10’
annotationProcessor ‘org.projectlombok1.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=“l(fā)ib/lombok.jar” /》
《/javac》
IDE
由于 Lombok 僅在編譯階段生成代碼,所以使用 Lombok 注解的源代碼,在 IDE 中會(huì)被高亮顯示錯(cuò)誤,針對(duì)這個(gè)問(wèn)題可以通過(guò)安裝 IDE 對(duì)應(yīng)的插件來(lái)解決。這里不詳細(xì)展開(kāi),具體的安裝方式可以參考:
https://www.baeldung.com/lombok-ide
0x03:Lombok 詳解
注意:以下示例所使用的 Lombok 版本是 1.18.10
3.1 @Getter and @Setter
你可以使用 @Getter 或 @Setter 注釋任何類(lèi)或字段,Lombok 會(huì)自動(dòng)生成默認(rèn)的 getter/setter 方法。
@Getter 注解
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Getter {
// 若getter方法非public的話,可以設(shè)置可訪問(wèn)級(jí)別
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è)置可訪問(wèn)級(jí)別
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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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í),會(huì)啟用延遲初始化,即當(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(“l(fā)azy”);
private String createValue(String name) {
System.out.println(“createValue(” + name + “)”);
return null;
}
}
以上代碼經(jīng)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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(“l(fā)azy”);
value = actualValue == null ? this.lazy : actualValue;
this.lazy.set(value);
}
}
}
return (String)((String)(value == this.lazy ? null : value));
}
}
通過(guò)以上代碼可知,調(diào)用 getLazy 方法時(shí),若發(fā)現(xiàn) value 為 null,則會(huì)在同步代碼塊中執(zhí)行初始化操作。
3.2 Constructor Annotations
@NoArgsConstructor
使用 @NoArgsConstructor 注解可以為指定類(lèi),生成默認(rèn)的構(gòu)造函數(shù),@NoArgsConstructor 注解的定義如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface NoArgsConstructor {
// 若設(shè)置該屬性,將會(huì)生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
String staticName() default “”;
AnyAnnotation[] onConstructor() default {};
// 設(shè)置生成構(gòu)造函數(shù)的訪問(wèn)級(jí)別,默認(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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
public class NoArgsConstructorDemo {
private long id;
private String name;
private int age;
private NoArgsConstructorDemo() {
}
public static NoArgsConstructorDemo getInstance() {
return new NoArgsConstructorDemo();
}
}
@AllArgsConstructor
使用 @AllArgsConstructor 注解可以為指定類(lèi),生成包含所有成員的構(gòu)造函數(shù),@AllArgsConstructor 注解的定義如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface AllArgsConstructor {
// 若設(shè)置該屬性,將會(huì)生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
String staticName() default “”;
AnyAnnotation[] onConstructor() default {};
// 設(shè)置生成構(gòu)造函數(shù)的訪問(wèn)級(jí)別,默認(rèn)是public
AccessLevel access() default lombok.AccessLevel.PUBLIC;
}
示例
@AllArgsConstructor
public class AllArgsConstructorDemo {
private long id;
private String name;
private int age;
}
以上代碼經(jīng)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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 注解可以為指定類(lèi)必需初始化的成員變量,如 final 成員變量,生成對(duì)應(yīng)的構(gòu)造函數(shù),@RequiredArgsConstructor 注解的定義如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface RequiredArgsConstructor {
// 若設(shè)置該屬性,將會(huì)生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
String staticName() default “”;
AnyAnnotation[] onConstructor() default {};
// 設(shè)置生成構(gòu)造函數(shù)的訪問(wèn)級(jí)別,默認(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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
public class RequiredArgsConstructorDemo {
private final long id;
private String name;
private int age;
public RequiredArgsConstructorDemo(long id) {
this.id = id;
}
}
3.3 @EqualsAndHashCode
使用 @EqualsAndHashCode 注解可以為指定類(lèi)生成 equals 和 hashCode 方法, @EqualsAndHashCode 注解的定義如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {
// 指定在生成的equals和hashCode方法中需要排除的字段列表
String[] exclude() default {};
// 顯式列出用于identity的字段,一般情況下non-static,non-transient字段會(huì)被用于identity
String[] of() default {};
// 標(biāo)識(shí)在執(zhí)行字段計(jì)算前,是否調(diào)用父類(lèi)的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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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 注解可以為指定類(lèi)生成 toString 方法, @ToString 注解的定義如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface ToString {
// 打印輸出時(shí)是否包含字段的名稱(chēng)
boolean includeFieldNames() default true;
// 列出打印輸出時(shí),需要排除的字段列表
String[] exclude() default {};
// 顯式的列出需要打印輸出的字段列表
String[] of() default {};
// 打印輸出的結(jié)果中是否包含父類(lèi)的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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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 的變體放在類(lèi)上(適用于你所使用的日志記錄系統(tǒng)的任何一種);之后,你將擁有一個(gè)靜態(tài)的 final log 字段,然后你就可以使用該字段來(lái)輸出日志。
@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í)例方法上。它的操作類(lèi)似于 synchronized 關(guān)鍵字,但是它鎖定在不同的對(duì)象上。synchronized 關(guān)鍵字應(yīng)用在實(shí)例方法時(shí),鎖定的是 this 對(duì)象,而應(yīng)用在靜態(tài)方法上鎖定的是類(lèi)對(duì)象。對(duì)于 @Synchronized 注解聲明的方法來(lái)說(shuō),它鎖定的是 或lock。@Synchronized 注解的定義如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Synchronized {
// 指定鎖定的字段名稱(chēng)
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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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 注解可以為指定類(lèi)實(shí)現(xiàn)建造者模式,該注解可以放在類(lèi)、構(gòu)造函數(shù)或方法上。@Builder 注解的定義如下:
@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {
@Target(FIELD)
@Retention(SOURCE)
public @interface Default {}
// 創(chuàng)建新的builder實(shí)例的方法名稱(chēng)
String builderMethodName() default “builder”;
// 創(chuàng)建Builder注解類(lèi)對(duì)應(yīng)實(shí)例的方法名稱(chēng)
String buildMethodName() default “build”;
// builder類(lèi)的名稱(chēng)
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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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)拋出已檢查的異常,而無(wú)需在方法中使用 throw 語(yǔ)句顯式拋出。@SneakyThrows 注解的定義如下:
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface SneakyThrows {
// 設(shè)置你希望向上拋的異常類(lèi)
Class《? extends Throwable》[] value() default java.lang.Throwable.class;
}
示例
public class SneakyThrowsDemo {
@SneakyThrows
@Override
protected Object clone() {
return super.clone();
}
}
以上代碼經(jīng)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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 注解,它將會(huì)為你自動(dòng)生成非空校驗(yàn)語(yǔ)句。@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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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í)行完畢退出之前會(huì)自動(dòng)清理資源,自動(dòng)生成 try-finally 這樣的代碼來(lái)關(guān)閉流。
@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.SOURCE)
public @interface Cleanup {
// 設(shè)置用于執(zhí)行資源清理/回收的方法名稱(chēng),對(duì)應(yīng)方法不能包含任何參數(shù),默認(rèn)名稱(chēng)為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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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
在類(lèi)的字段上應(yīng)用 @With 注解之后,將會(huì)自動(dòng)生成一個(gè) withFieldName(newValue) 的方法,該方法會(huì)基于 newValue 調(diào)用相應(yīng)構(gòu)造函數(shù),創(chuàng)建一個(gè)當(dāng)前類(lèi)對(duì)應(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)過(guò) Lombok 編譯后,會(huì)生成如下代碼:
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í)還會(huì)自動(dòng)進(jìn)行類(lèi)型推斷。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
”, 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
”, entry.getKey(), entry.getValue());
}
}
}
至此功能強(qiáng)大的 Lombok 工具就介紹完畢了。
source:https://www.yuque.com/fengzheng-fly67/zln9pu/hgu2wb
編輯:jq
-
JAVA
+關(guān)注
關(guān)注
19文章
2960瀏覽量
104562 -
IDE
+關(guān)注
關(guān)注
0文章
335瀏覽量
46681 -
Code
+關(guān)注
關(guān)注
0文章
68瀏覽量
15374 -
代碼
+關(guān)注
關(guān)注
30文章
4753瀏覽量
68368
原文標(biāo)題:Lombok 使用指南
文章出處:【微信號(hào):AndroidPush,微信公眾號(hào):Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論