摘要:不可用于類級別。是否使用父類的和方法,注意父類為時無法設置為。注解源代碼,另外兩個注解的源碼和這個很類似,就不貼出來了。過時的生成包含必須處理的字段的構造器,如修飾必須初始化注解修飾的。
相識
lombok想必已經有很多人已經使用了很長時間了,而我卻是第一次接觸到,有點呆。lombok主要是用于減少重復代碼,通過一組簡單的注釋取代一些重復的Java代碼。對于lombok的評價褒貶不一,有的人覺得特別方便,有的人覺得改變了一成不變的代碼結構,增加了代碼維護成本(有的人沒有用過lombok),我是覺得每一個工具誕生肯定是有他誕生的價值的,多學一個是一個啊,小老弟,用不用再說。:)
官方文檔地址
官方API地址
官方注解介紹地址
準備 1、下載idea插件我這里已經安裝好了,沒有安裝的時候按鈕應該是Install
2、pom文件引入project lombok的maven依賴org.projectlombok lombok 1.18.2 provided
lombok maven版本
注解介紹 @Getter和@Setter顧名思義,生成get和set方法的注解,@Getter和@Setter發生在編譯階段,編譯之后,@Getter和@Setter相關的注解就消失了,取而代之的是相應的get和set方法。
public class LombokTest { @Getter @Setter private boolean flag; }
lombok遵循了boolean類型的get方法的約定,我們來看一下編譯后的代碼(等效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方法的訪問級別。
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的訪問級別是protected。lombok提供了下面幾種級別。
AccessLevel枚舉類的源代碼。
public enum AccessLevel { PUBLIC, // public MODULE, // 編譯后相當于 default PROTECTED, // protected PACKAGE, // default PRIVATE, // private NONE; // 不生成 private AccessLevel() { } }
最后@Getter和@Setter注解是可以寫在類級別的,作用于所有的成員變量,無法細粒度的控制訪問級別。
@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注解使用在構造函數的字段時,構造函數也會進行空變量檢查。不可用于類級別。
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()方法。只能用于類級別。static修飾的變量是不能生成在toString()方法中的,原因是static修飾的變量在類創建的時候就生成了,只有一個;而普通的變量屬于對象,每創建一個新的對象都會有一個。可以理解為static修飾的變量屬于類,而普通變量數據對象,這樣可能好理解一點。
@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 + ")"; } }
默認情況下出了static修飾的字段都將以name-value的形式生成在toString()方法中。同時toString注解中還可以設置一些屬性來細粒度的控制toString()方法。
下面是ToString注解的源碼和解釋:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface ToString { boolean includeFieldNames() default true; // 生成toString()方法時默認為 name-value的形式,設置為false時 則 value的形式。 String[] exclude() default {}; // 不包含指定字段 String[] of() default {}; // 包含指定字段 boolean callSuper() default false; // 是否調用父類的toString()方法 boolean doNotUseGetters() default false; // 生成toString()方法是否直接訪問字段,設置為true時直接訪問字段(如:this.name),false時通過getter()方法進行訪問(如:this.getName())。當然如果沒有生成getter()方法,無論是否設置都直接訪問字段 boolean onlyExplicitlyIncluded() default false; // 是否僅僅包含添加了@ToString.Include的字段,默認為false。 @Target({ElementType.FIELD}) @Retention(RetentionPolicy.SOURCE) public @interface Exclude { // 使用@ToString.Exclude修飾字段,需要和@ToString注解一起使用,多帶帶使用無效。 } @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE) public @interface Include {// 使用@ToString.Include修飾字段,需要和@ToString注解一起使用,多帶帶使用無效。 int rank() default 0; String name() default ""; } }
注意:
of和exclude屬性設置多個字段時,以字符串數組的形式,如:
@ToString(of = {"name","phone"}) // 包含name和phone字段 @ToString(exclude = {"name","phone"}) // 不包含name和phone字段
使用@ToString.Include或者@ToString.Exclude注解時也需要使用@ToString注解,否者無效。
@ToString public class LombokTest { @ToString.Include private String name; @ToString.Exclude private String phone; }@EqualsAndHashCode
生成equals()和hashCode()方法。默認使用所有的非static和非transient字段生成這兩個方法。
@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注解相似也可以通過設置一些屬性來控制決堤生成的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時無法設置為true。 boolean doNotUseGetters() default false; EqualsAndHashCode.AnyAnnotation[] onParam() default {}; boolean onlyExplicitlyIncluded() default false; /** @deprecated */ @Deprecated @Retention(RetentionPolicy.SOURCE) @Target({}) public @interface AnyAnnotation { // 過時的方法(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中使用的最多的注解,相當于@ToString,@EqualsAndHashCode, @RequiredArgsConstructor,@Getter和@Setter五個注解的功能。雖然使用起來方法,但是失去了細粒度的控制。如果需要細粒度控制,則需要進行注解的覆蓋。
@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 ""; }
可以看到提供了一個,staticConstructor(),這個方法的作用是私有化構造器,并生成一個靜態的獲取實例的方法,這樣就可通過類名來獲取實例(如:LombokTest.getLombokTest())
@Data(staticConstructor = "getLombokTest")
private LombokTest() { } public static LombokTest getLombokTest() { return new LombokTest(); } // ...省略其他代碼@Cleanup
自動釋放資源,主要用于IO流的操作,不需要手動編寫釋放資源的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(); } } } }
還是挺方便的。再來看看@Cleanup注解的源代碼
@Target({ElementType.LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface Cleanup { String value() default "close"; }
可以看到默認調用的是close方法,也就是說我們可以設置finally方法體具體調用的流處理方法。如:
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代碼)
具體可以指定哪些字段,需要流對象支持哪些方法了。如InputStream:
@Synchronized同步代碼塊,只能使用在類方法(static)或者對象方法(普通方法)上,synchronized關鍵字鎖住的是this,@Synchronized注解默認使用的鎖為$lock,靜態的鎖為$LOCK,也可以自己指定鎖對象,如示例中的: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
個人覺得沒有啥意義,唯一的作用可能就是不用手動捕獲異常或者向上拋出,而是通過lombok幫你捕獲。。。可以指定捕獲的異常類型,默認捕獲的是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; } } }
感覺有點呆。。。官方建議在沒有深思熟慮之前不要使用這個注解。。。下面是官網上的一句話:
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 生成一個無參構造器。
@NoArgsConstructor注解源代碼,另外兩個注解的源碼和這個很類似,就不貼出來了。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface NoArgsConstructor { String staticName() default ""; // 如果指定了相應字段,則私有化構造并生成一個靜態的獲取實例方法。 NoArgsConstructor.AnyAnnotation[] onConstructor() default {}; AccessLevel access() default AccessLevel.PUBLIC; boolean force() default false; /** @deprecated */ @Deprecated @Retention(RetentionPolicy.SOURCE) @Target({}) public @interface AnyAnnotation { // 過時的(deprecated) } }
@ RequiredArgsConstructor 生成包含必須處理的字段的構造器,如: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 生成一個全參構造器,除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; } } }小結
學到這里常用的Lombok注解基本上都有了,如果想要根據深入的學習,建議去官網看。官網地址文章開始已經列出來了,加油!!!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75306.html
摘要:雖然有人可能會說里面都自帶自動生成這些方法的功能,但是使用會使你的代碼看起來更加簡潔,寫起來也更加方便。使用不使用自動生成方法使用不使用自動生成無參數構造函數。 一、lombok簡介 lombok是在學習過程中發現的一個非常好用的小工具,用了之后感覺的確很不錯,所以特此來推薦一下。 lombok的官方地址:https://projectlombok.org/ lombok的Github...
摘要:提高編碼效率使代碼更簡潔消除冗長代碼避免修改字段名字時忘記修改方法名提高下逼格以上就是的優點,當然,的優點遠遠不止以上幾點,使用,你可以更加優雅高效的編輯代碼。實戰完成了上述準備之后,就可以愉快的使用進行編碼了。接下來是使用簡化后的代碼。 Lombok介紹 近來偶遇一款擼碼神器,介紹給大家~相信許多小伙伴都深有體會,POJO類中的千篇一律的getter/setter,construct...
摘要:使用,簡化代碼為了簡化與,提供了一種機制,幫助我們自動生成這些樣板代碼。但是,在實際項目中,完全沒有使用到。源碼審查是一個源碼審查工具。最新版已經支持的全部注解,不再認為是沒有使用的變量。 一個典型的 Java 類 public class A { private int a; private String b; public int getA() { ret...
摘要:什么是一言以蔽之是一種工具,提供了簡單的注解來簡化我們的重復冗長代碼。但在實際的項目中,我們常常只在定義的時候用上,而在業務代碼中很少用到。總結是個非常有用的工具,能夠幫助我們精簡很多臃腫冗長的代碼,不過也有其局限性,推薦在定義中使用。 什么是Lombok 一言以蔽之:lombok是一種工具,提供了簡單的注解來簡化我們的重復冗長Java代碼。比如一個Java Bean,注解了lombo...
摘要:可以去下載包目前最新版本為。對于某個具體的類來說,出于安全或者性能或者其它方面的考慮,可能并不希望全部成員都出現在方法的返回值里。根據中的建議,方法和方法要同時實現,并且保證一致性。 前言 Lombok主頁 Lombok下載 Lombok引入項目之后,便可以使用 本文記錄了在項目中應用Lombok時的使用案例,希望對朋友你有一些幫助。 可以去 下載jar包 maven: ...
閱讀 2892·2021-11-24 09:38
閱讀 3515·2021-11-23 09:51
閱讀 980·2021-09-09 11:52
閱讀 4036·2021-08-11 11:18
閱讀 1115·2019-08-30 14:05
閱讀 3234·2019-08-30 11:23
閱讀 1771·2019-08-29 17:02
閱讀 1130·2019-08-26 13:49