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/