摘要:不可用于類級(jí)別。是否使用父類的和方法,注意父類為時(shí)無(wú)法設(shè)置為。注解源代碼,另外兩個(gè)注解的源碼和這個(gè)很類似,就不貼出來(lái)了。過時(shí)的生成包含必須處理的字段的構(gòu)造器,如修飾必須初始化注解修飾的。
相識(shí)
lombok想必已經(jīng)有很多人已經(jīng)使用了很長(zhǎng)時(shí)間了,而我卻是第一次接觸到,有點(diǎn)呆。lombok主要是用于減少重復(fù)代碼,通過一組簡(jiǎn)單的注釋取代一些重復(fù)的Java代碼。對(duì)于lombok的評(píng)價(jià)褒貶不一,有的人覺得特別方便,有的人覺得改變了一成不變的代碼結(jié)構(gòu),增加了代碼維護(hù)成本(有的人沒有用過lombok),我是覺得每一個(gè)工具誕生肯定是有他誕生的價(jià)值的,多學(xué)一個(gè)是一個(gè)啊,小老弟,用不用再說(shuō)。:)
官方文檔地址
官方API地址
官方注解介紹地址
準(zhǔn)備 1、下載idea插件我這里已經(jīng)安裝好了,沒有安裝的時(shí)候按鈕應(yīng)該是Install
2、pom文件引入project lombok的maven依賴org.projectlombok lombok 1.18.2 provided
lombok maven版本
注解介紹 @Getter和@Setter顧名思義,生成get和set方法的注解,@Getter和@Setter發(fā)生在編譯階段,編譯之后,@Getter和@Setter相關(guān)的注解就消失了,取而代之的是相應(yīng)的get和set方法。
public class LombokTest { @Getter @Setter private boolean flag; }
lombok遵循了boolean類型的get方法的約定,我們來(lái)看一下編譯后的代碼(等效Java代碼)吧。
public class LombokTest { private boolean flag; public LombokTest() { } public boolean isFlag() { return this.flag; } public void setFlag(boolean flag) { this.flag = flag; } }
可以看到boolean類型的get方法是isFlag()而不是getFlag()。我們還可定義生成get和set方法的訪問級(jí)別。
public class LombokTest { @Getter(AccessLevel.PUBLIC) @Setter(AccessLevel.PROTECTED) private String name; }
編譯后的代碼(等效Java代碼)
public class LombokTest { private String name; public LombokTest() { } public String getName() { return this.name; } protected void setName(String name) { this.name = name; } }
可以看到setName的訪問級(jí)別是protected。lombok提供了下面幾種級(jí)別。
AccessLevel枚舉類的源代碼。
public enum AccessLevel { PUBLIC, // public MODULE, // 編譯后相當(dāng)于 default PROTECTED, // protected PACKAGE, // default PRIVATE, // private NONE; // 不生成 private AccessLevel() { } }
最后@Getter和@Setter注解是可以寫在類級(jí)別的,作用于所有的成員變量,無(wú)法細(xì)粒度的控制訪問級(jí)別。
@Getter(AccessLevel.MODULE) @Setter(AccessLevel.PROTECTED) public class LombokTest { private String name; private boolean flag; }
編譯后的代碼(等效Java代碼)
public class LombokTest { private String name; private boolean flag; public LombokTest() { } String getName() { return this.name; } boolean isFlag() { return this.flag; } protected void setName(String name) { this.name = name; } protected void setFlag(boolean flag) { this.flag = flag; } }@NonNull
變量空檢查,如果@NonNull注解使用在構(gòu)造函數(shù)的字段時(shí),構(gòu)造函數(shù)也會(huì)進(jìn)行空變量檢查。不可用于類級(jí)別。
public class LombokTest { @NonNull @Setter @Getter private String name; public LombokTest(@NonNull String name) { this.name = name; } }
編譯后的代碼(等效Java代碼)
public class LombokTest { @NonNull private String name; public LombokTest(@NonNull String name) { if (name == null) { throw new NullPointerException("name is marked @NonNull but is null"); } else { this.name = name; } } public void setName(@NonNull String name) { if (name == null) { throw new NullPointerException("name is marked @NonNull but is null"); } else { this.name = name; } } @NonNull public String getName() { return this.name; } }@ToString
用于生成toString()方法。只能用于類級(jí)別。static修飾的變量是不能生成在toString()方法中的,原因是static修飾的變量在類創(chuàng)建的時(shí)候就生成了,只有一個(gè);而普通的變量屬于對(duì)象,每創(chuàng)建一個(gè)新的對(duì)象都會(huì)有一個(gè)。可以理解為static修飾的變量屬于類,而普通變量數(shù)據(jù)對(duì)象,這樣可能好理解一點(diǎn)。
@ToString public class LombokTest { private String name; private static String phone; }
編譯后的代碼(等效Java代碼)
public class LombokTest { private String name; private static String phone; public LombokTest() { } public String toString() { return "YmlProperties(name=" + this.name + ")"; } }
默認(rèn)情況下出了static修飾的字段都將以name-value的形式生成在toString()方法中。同時(shí)toString注解中還可以設(shè)置一些屬性來(lái)細(xì)粒度的控制toString()方法。
下面是ToString注解的源碼和解釋:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface ToString { boolean includeFieldNames() default true; // 生成toString()方法時(shí)默認(rèn)為 name-value的形式,設(shè)置為false時(shí) 則 value的形式。 String[] exclude() default {}; // 不包含指定字段 String[] of() default {}; // 包含指定字段 boolean callSuper() default false; // 是否調(diào)用父類的toString()方法 boolean doNotUseGetters() default false; // 生成toString()方法是否直接訪問字段,設(shè)置為true時(shí)直接訪問字段(如:this.name),false時(shí)通過getter()方法進(jìn)行訪問(如:this.getName())。當(dāng)然如果沒有生成getter()方法,無(wú)論是否設(shè)置都直接訪問字段 boolean onlyExplicitlyIncluded() default false; // 是否僅僅包含添加了@ToString.Include的字段,默認(rèn)為false。 @Target({ElementType.FIELD}) @Retention(RetentionPolicy.SOURCE) public @interface Exclude { // 使用@ToString.Exclude修飾字段,需要和@ToString注解一起使用,多帶帶使用無(wú)效。 } @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE) public @interface Include {// 使用@ToString.Include修飾字段,需要和@ToString注解一起使用,多帶帶使用無(wú)效。 int rank() default 0; String name() default ""; } }
注意:
of和exclude屬性設(shè)置多個(gè)字段時(shí),以字符串?dāng)?shù)組的形式,如:
@ToString(of = {"name","phone"}) // 包含name和phone字段 @ToString(exclude = {"name","phone"}) // 不包含name和phone字段
使用@ToString.Include或者@ToString.Exclude注解時(shí)也需要使用@ToString注解,否者無(wú)效。
@ToString public class LombokTest { @ToString.Include private String name; @ToString.Exclude private String phone; }@EqualsAndHashCode
生成equals()和hashCode()方法。默認(rèn)使用所有的非static和非transient字段生成這兩個(gè)方法。
@EqualsAndHashCode public class LombokTest { private String name; private String phone; private boolean flag; }
編譯后的代碼(等效Java代碼)
public class LombokTest { private String name; private String phone; private boolean flag; public LombokTest() { } public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof LombokTest)) { return false; } else { LombokTest other = (LombokTest)o; if (!other.canEqual(this)) { return false; } else { label39: { Object this$name = this.name; Object other$name = other.name; if (this$name == null) { if (other$name == null) { break label39; } } else if (this$name.equals(other$name)) { break label39; } return false; } Object this$phone = this.phone; Object other$phone = other.phone; if (this$phone == null) { if (other$phone != null) { return false; } } else if (!this$phone.equals(other$phone)) { return false; } if (this.flag != other.flag) { return false; } else { return true; } } } } protected boolean canEqual(Object other) { return other instanceof LombokTest; } public int hashCode() { int PRIME = true; int result = 1; Object $name = this.name; int result = result * 59 + ($name == null ? 43 : $name.hashCode()); Object $phone = this.phone; result = result * 59 + ($phone == null ? 43 : $phone.hashCode()); result = result * 59 + (this.flag ? 79 : 97); return result; } }
和ToString注解相似也可以通過設(shè)置一些屬性來(lái)控制決堤生成的hashCode()和equals()方法。下面是@EqualsAndHashCode注解的源碼和解釋,和@ToString一樣的屬性就沒有寫注釋了。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface EqualsAndHashCode { String[] exclude() default {}; String[] of() default {}; boolean callSuper() default false;// 是否使用父類的equals和toString方法,注意:父類為Object時(shí)無(wú)法設(shè)置為true。 boolean doNotUseGetters() default false; EqualsAndHashCode.AnyAnnotation[] onParam() default {}; boolean onlyExplicitlyIncluded() default false; /** @deprecated */ @Deprecated @Retention(RetentionPolicy.SOURCE) @Target({}) public @interface AnyAnnotation { // 過時(shí)的方法(deprecated) } @Target({ElementType.FIELD}) @Retention(RetentionPolicy.SOURCE) public @interface Exclude { } @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE) public @interface Include { String replaces() default ""; } }@Data
這是lombok中使用的最多的注解,相當(dāng)于@ToString,@EqualsAndHashCode, @RequiredArgsConstructor,@Getter和@Setter五個(gè)注解的功能。雖然使用起來(lái)方法,但是失去了細(xì)粒度的控制。如果需要細(xì)粒度控制,則需要進(jìn)行注解的覆蓋。
@Data public class LombokTest { private String name; private String phone; private boolean flag; }
編譯后的代碼(等效Java代碼)
public class LombokTest { private String name; private String phone; private boolean flag; public LombokTest() { } public String getName() { return this.name; } public String getPhone() { return this.phone; } public boolean isFlag() { return this.flag; } public void setName(String name) { this.name = name; } public void setPhone(String phone) { this.phone = phone; } public void setFlag(boolean flag) { this.flag = flag; } public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof LombokTest)) { return false; } else { LombokTest other = (LombokTest)o; if (!other.canEqual(this)) { return false; } else { label39: { Object this$name = this.getName(); Object other$name = other.getName(); if (this$name == null) { if (other$name == null) { break label39; } } else if (this$name.equals(other$name)) { break label39; } return false; } Object this$phone = this.getPhone(); Object other$phone = other.getPhone(); if (this$phone == null) { if (other$phone != null) { return false; } } else if (!this$phone.equals(other$phone)) { return false; } if (this.isFlag() != other.isFlag()) { return false; } else { return true; } } } } protected boolean canEqual(Object other) { return other instanceof LombokTest; } public int hashCode() { int PRIME = true; int result = 1; Object $name = this.getName(); int result = result * 59 + ($name == null ? 43 : $name.hashCode()); Object $phone = this.getPhone(); result = result * 59 + ($phone == null ? 43 : $phone.hashCode()); result = result * 59 + (this.isFlag() ? 79 : 97); return result; } public String toString() { return "LombokTest(name=" + this.getName() + ", phone=" + this.getPhone() + ", flag=" + this.isFlag() + ")"; } }
下面看一下@Data注解的源碼。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface Data { String staticConstructor() default ""; }
可以看到提供了一個(gè),staticConstructor(),這個(gè)方法的作用是私有化構(gòu)造器,并生成一個(gè)靜態(tài)的獲取實(shí)例的方法,這樣就可通過類名來(lái)獲取實(shí)例(如:LombokTest.getLombokTest())
@Data(staticConstructor = "getLombokTest")
private LombokTest() { } public static LombokTest getLombokTest() { return new LombokTest(); } // ...省略其他代碼@Cleanup
自動(dòng)釋放資源,主要用于IO流的操作,不需要手動(dòng)編寫釋放資源的try/finally代碼塊。
public class LombokTest { public static void main(String[] args) throws Exception { @Cleanup InputStream is = new FileInputStream(args[0]); @Cleanup OutputStream os = new FileOutputStream(args[0]); } }
編譯后的代碼(等效Java代碼)
public class LombokTest { public static void main(String[] args) throws Exception { FileInputStream is = new FileInputStream(args[0]); try { OutputStream os = new FileOutputStream(args[0]); if (Collections.singletonList(os).get(0) != null) { os.close(); } } finally { if (Collections.singletonList(is).get(0) != null) { is.close(); } } } }
還是挺方便的。再來(lái)看看@Cleanup注解的源代碼
@Target({ElementType.LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface Cleanup { String value() default "close"; }
可以看到默認(rèn)調(diào)用的是close方法,也就是說(shuō)我們可以設(shè)置finally方法體具體調(diào)用的流處理方法。如:
public static void main(String[] args) throws Exception { @Cleanup(value = "available") InputStream is = new FileInputStream(args[0]); @Cleanup OutputStream os = new FileOutputStream(args[0]); }
編譯后的代碼(等效Java代碼)
具體可以指定哪些字段,需要流對(duì)象支持哪些方法了。如InputStream:
@Synchronized同步代碼塊,只能使用在類方法(static)或者對(duì)象方法(普通方法)上,synchronized關(guān)鍵字鎖住的是this,@Synchronized注解默認(rèn)使用的鎖為$lock,靜態(tài)的鎖為$LOCK,也可以自己指定鎖對(duì)象,如示例中的:world
public class LombokTest { @Synchronized public void hello() { } @Synchronized public static void helloWorld() { } private final Object world = new Object(); @Synchronized("world") public void world() { } }
編譯后的代碼(等效Java代碼)
public class LombokTest { private final Object $lock = new Object[0]; private static final Object $LOCK = new Object[0]; private final Object world = new Object(); public LombokTest() { } public void hello() { Object var1 = this.$lock; synchronized(this.$lock) { ; } } public static void helloWorld() { Object var0 = $LOCK; synchronized($LOCK) { ; } } public void world() { Object var1 = this.world; synchronized(this.world) { ; } } }@SneakyThrows
個(gè)人覺得沒有啥意義,唯一的作用可能就是不用手動(dòng)捕獲異?;蛘呦蛏蠏伋?,而是通過lombok幫你捕獲。。??梢灾付ú东@的異常類型,默認(rèn)捕獲的是Throwable。
public class LombokTest { @SneakyThrows() public void testSneakyThrows() { throw new IllegalAccessException(); } @SneakyThrows(IllegalAccessException.class) public void testSneakyThrows2() { throw new IllegalAccessException(); } }
編譯后的代碼(等效Java代碼)
public class LombokTest { public LombokTest() { } public void testSneakyThrows() { try { throw new IllegalAccessException(); } catch (Throwable var2) { throw var2; } } public void testSneakyThrows2() { try { throw new IllegalAccessException(); } catch (IllegalAccessException var2) { throw var2; } } }
感覺有點(diǎn)呆。。。官方建議在沒有深思熟慮之前不要使用這個(gè)注解。。。下面是官網(wǎng)上的一句話:
You can pass any number of exceptions to the @SneakyThrows annotation. If you pass no exceptions, you may throw any exception sneakily.
@NoArgsConstructor,@ RequiredArgsConstructor,@ AllArgsConstructor@NoArgsConstructor 生成一個(gè)無(wú)參構(gòu)造器。
@NoArgsConstructor注解源代碼,另外兩個(gè)注解的源碼和這個(gè)很類似,就不貼出來(lái)了。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface NoArgsConstructor { String staticName() default ""; // 如果指定了相應(yīng)字段,則私有化構(gòu)造并生成一個(gè)靜態(tài)的獲取實(shí)例方法。 NoArgsConstructor.AnyAnnotation[] onConstructor() default {}; AccessLevel access() default AccessLevel.PUBLIC; boolean force() default false; /** @deprecated */ @Deprecated @Retention(RetentionPolicy.SOURCE) @Target({}) public @interface AnyAnnotation { // 過時(shí)的(deprecated) } }
@ RequiredArgsConstructor 生成包含必須處理的字段的構(gòu)造器,如:final修飾(必須初始化)、@NonNull注解修飾的。
@RequiredArgsConstructor public class LombokTest { private String name; private String phone; private transient boolean flag; private final String finalFiled; private static int num; }
編譯后的代碼(等效Java代碼)
public class LombokTest { private String name; private String phone; private transient boolean flag; private final String finalFiled; private static int num; public LombokTest(String finalFiled) { this.finalFiled = finalFiled; } }
@ AllArgsConstructor 生成一個(gè)全參構(gòu)造器,除static修飾的字段。@NonNull可以組合使用。
@AllArgsConstructor public class LombokTest { private String name; @NonNull private String phone; private transient boolean flag; private final String finalFiled; private static int num; }
編譯后的代碼(等效Java代碼)
public class LombokTest { private String name; @NonNull private String phone; private transient boolean flag; private final String finalFiled; private static int num; public LombokTest(String name, @NonNull String phone, boolean flag, String finalFiled) { if (phone == null) { throw new NullPointerException("phone is marked @NonNull but is null"); } else { this.name = name; this.phone = phone; this.flag = flag; this.finalFiled = finalFiled; } } }小結(jié)
學(xué)到這里常用的Lombok注解基本上都有了,如果想要根據(jù)深入的學(xué)習(xí),建議去官網(wǎng)看。官網(wǎng)地址文章開始已經(jīng)列出來(lái)了,加油!??!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75306.html
摘要:雖然有人可能會(huì)說(shuō)里面都自帶自動(dòng)生成這些方法的功能,但是使用會(huì)使你的代碼看起來(lái)更加簡(jiǎn)潔,寫起來(lái)也更加方便。使用不使用自動(dòng)生成方法使用不使用自動(dòng)生成無(wú)參數(shù)構(gòu)造函數(shù)。 一、lombok簡(jiǎn)介 lombok是在學(xué)習(xí)過程中發(fā)現(xiàn)的一個(gè)非常好用的小工具,用了之后感覺的確很不錯(cuò),所以特此來(lái)推薦一下。 lombok的官方地址:https://projectlombok.org/ lombok的Github...
摘要:提高編碼效率使代碼更簡(jiǎn)潔消除冗長(zhǎng)代碼避免修改字段名字時(shí)忘記修改方法名提高下逼格以上就是的優(yōu)點(diǎn),當(dāng)然,的優(yōu)點(diǎn)遠(yuǎn)遠(yuǎn)不止以上幾點(diǎn),使用,你可以更加優(yōu)雅高效的編輯代碼。實(shí)戰(zhàn)完成了上述準(zhǔn)備之后,就可以愉快的使用進(jìn)行編碼了。接下來(lái)是使用簡(jiǎn)化后的代碼。 Lombok介紹 近來(lái)偶遇一款擼碼神器,介紹給大家~相信許多小伙伴都深有體會(huì),POJO類中的千篇一律的getter/setter,construct...
摘要:使用,簡(jiǎn)化代碼為了簡(jiǎn)化與,提供了一種機(jī)制,幫助我們自動(dòng)生成這些樣板代碼。但是,在實(shí)際項(xiàng)目中,完全沒有使用到。源碼審查是一個(gè)源碼審查工具。最新版已經(jīng)支持的全部注解,不再認(rèn)為是沒有使用的變量。 一個(gè)典型的 Java 類 public class A { private int a; private String b; public int getA() { ret...
摘要:什么是一言以蔽之是一種工具,提供了簡(jiǎn)單的注解來(lái)簡(jiǎn)化我們的重復(fù)冗長(zhǎng)代碼。但在實(shí)際的項(xiàng)目中,我們常常只在定義的時(shí)候用上,而在業(yè)務(wù)代碼中很少用到??偨Y(jié)是個(gè)非常有用的工具,能夠幫助我們精簡(jiǎn)很多臃腫冗長(zhǎng)的代碼,不過也有其局限性,推薦在定義中使用。 什么是Lombok 一言以蔽之:lombok是一種工具,提供了簡(jiǎn)單的注解來(lái)簡(jiǎn)化我們的重復(fù)冗長(zhǎng)Java代碼。比如一個(gè)Java Bean,注解了lombo...
摘要:可以去下載包目前最新版本為。對(duì)于某個(gè)具體的類來(lái)說(shuō),出于安全或者性能或者其它方面的考慮,可能并不希望全部成員都出現(xiàn)在方法的返回值里。根據(jù)中的建議,方法和方法要同時(shí)實(shí)現(xiàn),并且保證一致性。 前言 Lombok主頁(yè) Lombok下載 Lombok引入項(xiàng)目之后,便可以使用 本文記錄了在項(xiàng)目中應(yīng)用Lombok時(shí)的使用案例,希望對(duì)朋友你有一些幫助。 可以去 下載jar包 maven: ...
閱讀 2907·2021-11-24 09:38
閱讀 3522·2021-11-23 09:51
閱讀 993·2021-09-09 11:52
閱讀 4043·2021-08-11 11:18
閱讀 1119·2019-08-30 14:05
閱讀 3237·2019-08-30 11:23
閱讀 1775·2019-08-29 17:02
閱讀 1135·2019-08-26 13:49