JAVA中,咱們常常要寫很是多的樣板文件,好比 set get方法,重寫equals hashcode方法等,這些代碼百年不變,lombok提供了一系列的註解讓你擺脫這些魔板代碼的書寫。html
使用lombok須要使ide工具支持,不然會出現找不到set 和get方法。本文以idea爲例,eclipse的話須要自行下載jar並配置 eclipse.ini文件參數具體百度。java
idea的話去plugins 搜索lombok,選擇 lombok plugin 點擊右側install 安裝完重啓便可。git
使用,在maven項目的pom.xml中引入:github
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.16</version> </dependency>
接下來就可使用lombok提供的註解了,咱們一個一個介紹。web
假設咱們有一個實體類:apache
public class Role implements Serializable { private static final long serialVersionUID = -1L; private Long id; // uuid生成 private String cname; private String ename; private String comments; }
這兩個註解@Getter 和 @Setter 若是標註在單個屬性上面則只對當前標註屬性起做用。api
public class Role implements Serializable { private static final long serialVersionUID = -1L; @Getter@Setter private Long id; // uuid生成 private String cname; private String ename; private String comments; }
此時你就不須要再寫id的get 和 set方法了。eclipse
若是你的字段不少,你能夠將這兩個註解寫在Role類上面,這樣就實現了全部的屬性的set get方法。maven
咱們還能夠制定生成的set get方法的訪問權限:ide
@Setter(AccessLevel.PROTECTED)
@NonNull註解是不容許爲空,讓咱們看下面的lombok最終生成的例子:
@Getter @Setter @NonNull private List<Person> members;
等價於:
@NonNull private List<Person> members; public Family(@NonNull final List<Person> members) { if (members == null) throw new java.lang.NullPointerException("members"); this.members = members; } @NonNull public List<Person> getMembers() { return members; } public void setMembers(@NonNull final List<Person> members) { if (members == null) throw new java.lang.NullPointerException("members"); this.members = members; }
這個註釋生成toString方法的實現。默認狀況下,任何非靜態字段將包含在輸出方法的名稱-值對。若是須要不打印某些屬性,能夠經過設置註釋參數includeFieldNames爲false。
@ToString(callSuper=true,exclude="someExcludedField") public class Foo extends Bar { private boolean someBoolean = true; private String someStringField; private float someExcludedField; }
等價於:
public class Foo extends Bar { private boolean someBoolean = true; private String someStringField; private float someExcludedField; @java.lang.Override public java.lang.String toString() { return "Foo(super=" + super.toString() + ", someBoolean=" + someBoolean + ", someStringField=" + someStringField + ")"; } }
這個是類級別註釋,將生成equals和hashCode方法,本質上二者是聯繫在一塊兒的。默認狀況下,類中的任何非靜態字段將包含在方法中。就像@ToString排除參數提供給防止領域包括在生成的邏輯。
@EqualsAndHashCode(callSuper=true,exclude={"address","city","state","zip"}) public class Person extends SentientBeing { enum Gender { Male, Female } @NonNull private String name; @NonNull private Gender gender; private String ssn; private String address; private String city; private String state; private String zip; }
等價於:
public class Person extends SentientBeing { enum Gender { /*public static final*/ Male /* = new Gender() */, /*public static final*/ Female /* = new Gender() */; } @NonNull private String name; @NonNull private Gender gender; private String ssn; private String address; private String city; private String state; private String zip; @java.lang.Override public boolean equals(final java.lang.Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != this.getClass()) return false; if (!super.equals(o)) return false; final Person other = (Person)o; if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false; if (this.gender == null ? other.gender != null : !this.gender.equals(other.gender)) return false; if (this.ssn == null ? other.ssn != null : !this.ssn.equals(other.ssn)) return false; return true; } @java.lang.Override public int hashCode() { final int PRIME = 31; int result = 1; result = result * PRIME + super.hashCode(); result = result * PRIME + (this.name == null ? 0 : this.name.hashCode()); result = result * PRIME + (this.gender == null ? 0 : this.gender.hashCode()); result = result * PRIME + (this.ssn == null ? 0 : this.ssn.hashCode()); return result; } }
@data註釋多是最經常使用的註釋在Project Lombok工具集。它結合了@ToString的功能、@EqualsAndHashCode @ getter和@ setter。
@Data(staticConstructor="of") public class Company { private final Person founder; private String name; private List<Person> employees; }
等價於:
public class Company { private final Person founder; private String name; private List<Person> employees; private Company(final Person founder) { this.founder = founder; } public static Company of(final Person founder) { return new Company(founder); } public Person getFounder() { return founder; } public String getName() { return name; } public void setName(final String name) { this.name = name; } public List<Person> getEmployees() { return employees; } public void setEmployees(final List<Person> employees) { this.employees = employees; } @java.lang.Override public boolean equals(final java.lang.Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != this.getClass()) return false; final Company other = (Company)o; if (this.founder == null ? other.founder != null : !this.founder.equals(other.founder)) return false; if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false; if (this.employees == null ? other.employees != null : !this.employees.equals(other.employees)) return false; return true; } @java.lang.Override public int hashCode() { final int PRIME = 31; int result = 1; result = result * PRIME + (this.founder == null ? 0 : this.founder.hashCode()); result = result * PRIME + (this.name == null ? 0 : this.name.hashCode()); result = result * PRIME + (this.employees == null ? 0 : this.employees.hashCode()); return result; } @java.lang.Override public java.lang.String toString() { return "Company(founder=" + founder + ", name=" + name + ", employees=" + employees + ")"; } }
@Cleanup註釋可用於確保分配的資源被釋放。當一個局部變量被@Cleanup註釋,任何包裝在一個try / finally塊的代碼,保證在當前的做用域調用結束後被清理。
這個註解使用的時候要慎重一些:
若是使用了這個註解,他將拋出全部異常,官方建議使用java7 提供的try()代碼塊自動關閉,而且官方說這個註解可能在之後的版本刪除掉。
public void testCleanUp() { try { @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write(new byte[] {'Y','e','s'}); System.out.println(baos.toString()); } catch (IOException e) { e.printStackTrace(); } }
等價於:
public void testCleanUp() { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { baos.write(new byte[]{'Y', 'e', 's'}); System.out.println(baos.toString()); } finally { baos.close(); } } catch (IOException e) { e.printStackTrace(); } }
使用這個註解會爲你生成一個$object 所對象:
private DateFormat format = new SimpleDateFormat("MM-dd-YYYY"); @Synchronized public String synchronizedFormat(Date date) { return format.format(date); }
等價於:
private final java.lang.Object $lock = new java.lang.Object[0]; private DateFormat format = new SimpleDateFormat("MM-dd-YYYY"); public String synchronizedFormat(Date date) { synchronized ($lock) { return format.format(date); } }
使用它能夠將你想拋出的異常拋出,而不須要try catch。
import lombok.SneakyThrows; public class SneakyThrowsExample implements Runnable { @SneakyThrows public String utf8ToString(byte[] bytes) { return new String(bytes, "UTF-8"); } @SneakyThrows public void run() { throw new Throwable(); } }
等價於:
import java.io.UnsupportedEncodingException; import lombok.Lombok; public class SneakyThrowsExample implements Runnable { public String utf8ToString(byte[] bytes) { try { return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { throw Lombok.sneakyThrow(e); } } public void run() { try { throw new Throwable(); } catch (Throwable t) { throw Lombok.sneakyThrow(t); } } }
這個裏面包含的比較多,當咱們使用log的時候,在每一個類裏面都要引入 Log log=LogManager.xxxxx;使用這個註解後你能夠一樣使用你以前的配置,而且只須要引入一個註解,便可在代碼塊中使用log功能。
//下面這些是每一個註解所對應的自動生成的log對象類別 @CommonsLog private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class); @JBossLog Creates private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class); @Log Creates private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName()); @Log4j Creates private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class); @Log4j2 Creates private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class); @Slf4j Creates private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class); @XSlf4j Creates private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
看一個使用案例:
import lombok.extern.java.Log; import lombok.extern.slf4j.Slf4j; @Log public class LogExample { public static void main(String... args) { log.error("Something's wrong here"); } } @Slf4j public class LogExampleOther { public static void main(String... args) { log.error("Something else is wrong here"); } } @CommonsLog(topic="CounterLog") public class LogExampleCategory { public static void main(String... args) { log.error("Calling the 'CounterLog' with a message"); } }
等價於:
public class LogExampleOther { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class); public static void main(String... args) { log.error("Something else is wrong here"); } }
@Accessors(chain = true)
鏈式調用
@Accessors(chain = true) @Setter @Getter public class Student { private String name; private int age; }
建立對象使用的時候:
Student student = new Student() .setAge(24) .setName("zs");
@RequiredArgsConstructor
這個註解可讓咱們快速的構建一個須要傳參的構造函數:
@Accessors(chain = true) @Setter @Getter @RequiredArgsConstructor(staticName = "ofName") public class Student { @NonNull private String name; private int age; }
使用的時候:
Student student = Student.ofName("zs");
@Builder
使用構建者模式構建對象,咱們使用guava的時候能夠看到,不少api使用builder模式,這樣看着更簡潔。
@Builder public class Student { private String name; private int age; }
使用:
Student student = Student.builder().name("zs").age(24).build();
你懂得,雖然簡潔了,可是你依賴住了lombok 會在類上生成一堆註解,好比你使用hibernate的時候。
引用:
http://jnb.ociweb.com/jnb/jnbJan2010.html#intro
http://lrwinx.github.io/2017/03/04/%E7%BB%86%E6%80%9D%E6%9E%81%E6%81%90-%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BC%9A%E5%86%99java%E5%90%97/