一、Lombok原理(参考网上的博客)
自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。
lombok本质上就是这样的一个实现了"JSR 269 API"的程序。在使用javac的过程中,Lombok支持了JSR 269 Pluable Annotation Processing API(JSR 269 可插入注解过程接口),实现了JSR 269 API ,在编译时,Javac编译源码的具体流程如下:


首先有源代码,javac对源代码进行分析,生成一棵抽象语法树AST,运行过程中调用了实现了JSR 269 API 规范的Lombok程序,即Lombok Annotation Proceesor (Lombok 注解的处理器)。这时候,Lombok Annotation Processor对刚刚生成的AST进行处理,交递给Lombok Annotation Handler,Lombok Annotation Handler负责找到Lombok注解所在的类对应的语法树,然后修改该语法树(修改的内容为在AST中增加了set get 或其他方法定义的相应树节点),Lombok Annotation Processor这个处理器之后输出修改后的抽象语法树,拿到修改后的语法树后,最后进行解析和生成字节码文件。
步骤:
- javac对源代码进行分析,生成一棵抽象语法树(AST)
- 运行过程中调用实现了"JSR 269 API"的lombok程序
- 此时lombok就对第一步骤得到的AST进行处理,找到@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),增加getter和setter方法定义的相应树节点
- javac使用修改后的抽象语法树(AST)生成字节码文件
二、lombok注解
@Getter
给所有字段生成getter方法
有一个不太常用的功能
@Getter(lazy = true)
标注字段为懒加载字段,懒加载字段在创建对象时不会进行初始化,而是在第一次访问的时候才会初始化,后面再次访问也不会重复初始化

对照代码:
public class LombokDemo {
private final List<String> list = getListFromCache();
private List<String> getListFromCache() {
System.out.println("getListFromCache");
return new ArrayList<>();
}
public static void main(String[] args) {
LombokDemo lombokDemo = new LombokDemo();
System.out.println("-----------");
System.out::println(lombokDemo.list);
}
}
运行main方法,初始化对象LombokDemo时,会调用getListFromCache()方法,如下图所示:

代码:
public class LombokDemo {
@Getter(lazy = true)
private final List<String> list = getListFromCache();
private List<String> getListFromCache() {
System.out.println("getListFromCache");
return new ArrayList<>();
}
public static void main(String[] args) {
LombokDemo lombokDemo = new LombokDemo();
System.out.println("-----------");
lombokDemo.getList(); // 使用注解 @Getter(lazy = true)后会生成这样一个getter方法
}
}
生成:
public class LombokDemo {
private final AtomicReference<Object> list = new AtomicReference();
public LombokDemo() {
}
private List<String> getListFromCache() {
System.out.println("getListFromCache");
return new ArrayList();
}
public static void main(String[] args) {
LombokDemo lombokDemo = new LombokDemo();
System.out.println("-----------");
lombokDemo.getList();
}
public List<String> getList() {
Object value = this.list.get();
if (value == null) {
synchronized(this.list) {
value = this.list.get();
if (value == null) {
List<String> actualValue = this.getListFromCache();
value = actualValue == null ? this.list : actualValue;
this.list.set(value);
}
}
}
return (List)((List)(value == this.list ? null : value));
}
}
@Setter
给所有字段生成setter方法
注意:可以注解到字段或者类上(注解在类上会为类中的所有字段生成Getter和Setter方法),默认是public类型的,如果需要的话可以修改方法的访问级别。
如:
public class Emp {
@Getter
private Integer empno;
@Getter(AccessLevel.PROTECTED)
private String ename;
@Setter(AccessLevel.PRIVATE)
private String job;
@Getter
@Setter
private Integer mgr;
private LocalDate hiredate;
}
@Getter
@Setter
public class User {
private String name;
private Integer age;
private String sn;
private Long id;
private String username;
private String password;
}
@NonNull
判断是否为空,如果为空,则抛出java.lang.NullPointerException
@Getter
@Setter
public class Emp {
@NonNull
private Integer empno;
private String ename;
}
生成:
public class Emp {
@NonNull
private Integer empno;
private String ename;
public Emp() {
}
@NonNull
public Integer getEmpno() {
return this.empno;
}
public void setEmpno(@NonNull Integer empno) {
if (empno == null) {
throw new NullPointerException("empno is marked non-null but is null");
} else {
this.empno = empno;
}
}
public String getEname() {
return this.ename;
}
public void setEname(String ename) {
this.ename = ename;
}
}
@NoArgsConstructor
自动生成无参数构造函数。
生成一个无参构造方法。当类中有final字段没有被初始化时,编译器会报错,此时可用@NoArgsConstructor(force = true),然后就会为没有初始化的final字段设置默认值 0 / false / null, 这样编译器就不会报错。
对于具有约束的字段(例如@NonNull字段),不会生成检查或分配,因此请注意,正确初始化这些字段之前,这些约束无效。
final字段未初始化编译器报错:

@Setter
@NoArgsConstructor(force = true)
public class Emp {
@NonNull
private Integer empno;
private final String ename;
}
生成:
public class Emp {
@NonNull
private Integer empno;
private final String ename = null;
public static void main(String[] args) {
System.out.println(5);
}
public void setEmpno(@NonNull Integer empno) {
if (empno == null) {
throw new NullPointerException("empno is marked non-null but is null");
} else {
this.empno = empno;
}
}
public Emp() {
}
}
@RequiredArgsConstructor
生成构造方法(可能带参数也可能不带参数),如果带参数,这参数只能是以final修饰的未经初始化的字段,
也可以与NonNull配合使用,以@NonNull注解的未经初始化的字段。
@RequiredArgsConstructor(staticName = “of”)会生成一个of()的静态方法,并把构造方法设置为私有的
示例一:生成不带参数的构造方法
@RequiredArgsConstructor
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
}
生成代码:
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
public static void main(String[] args) {
System.out.println(5);
}
public Emp() {
}
}
示例二:参数只能是以final修饰的未经初始化的字段,或者是以@NonNull注解的未经初始化的字段
源代码
@RequiredArgsConstructor
public class Emp {
@NotNull
private Integer empno;
@NotNull
private String ename = "zhangsan";
private final String job;
private final Integer mgr =1234;
private LocalDate hiredate;
}
生成代码:
public class Emp {
@NotNull
private Integer empno;
@NotNull
private String ename;
private final String job;
private final Integer mgr;
private LocalDate hiredate;
public Emp(@NotNull Integer empno, String job) {
if (empno == null) {
$$$reportNull$$$0(0);
}
super();
this.ename = "zhangsan";
this.mgr = 1234;
if (empno == null) {
throw new NullPointerException("empno is marked non-null but is null");
} else {
this.empno = empno;
this.job = job;
}
}
}
示例三:生成一个of()的静态方法,并把构造方法设置为私有
源代码
@RequiredArgsConstructor( staticName = "of")
public class Emp {
@NotNull
private Integer empno;
@NotNull
private String ename = "zhangsan";
private final String job;
private final Integer mgr =1234;
private LocalDate hiredate;
}
生成代码:
public class Emp {
@NotNull
private Integer empno;
@NotNull
private String ename;
private final String job;
private final Integer mgr;
private LocalDate hiredate;
private Emp(@NotNull Integer empno, String job) {
if (empno == null) {
$$$reportNull$$$0(0);
}
super();
this.ename = "zhangsan";
this.mgr = 1234;
if (empno == null) {
throw new NullPointerException("empno is marked non-null but is null");
} else {
this.empno = empno;
this.job = job;
}
}
public static Emp of(@NotNull Integer empno, String job) {
if (empno == null) {
$$$reportNull$$$0(1);
}
return new Emp(empno, job);
}
}
@AllArgsConstructor
自动生成全参数构造函数。
注意下面的代码,加上字段加上final修饰和@NonNull注解后的效果:
@AllArgsConstructor
public class Emp {
@NotNull
private Integer empno;
@NotNull
private String ename = "zhangsan";
private final String job;
private final Integer mgr =1234; //不会出现在生成的构造方法中
private LocalDate hiredate;
}
生成:
public class Emp {
@NotNull
private Integer empno;
@NotNull
private String ename;
private final String job;
private final Integer mgr;
private LocalDate hiredate;
public Emp(@NotNull Integer empno, @NotNull String ename, String job, LocalDate hiredate) {
if (empno == null) {
$$$reportNull$$$0(0);
}
if (ename == null) {
$$$reportNull$$$0(1);
}
super();
this.ename = "zhangsan";
this.mgr = 1234;
if (empno == null) {
throw new NullPointerException("empno is marked non-null but is null");
} else if (ename == null) {
throw new NullPointerException("ename is marked non-null but is null");
} else {
this.empno = empno;
this.ename = ename;
this.job = job;
this.hiredate = hiredate;
}
}
}
注意:如果要同时生成默认构造方法、指定参数构造方法、全参构造方法,可以采用Lombok自动生成无参和全参的构造方法的注解,然后手工添加指定参数的构造方法
@ToString
调用toString()方法的时候,输出类的所有属性值
该注解有以下多个属性可以进一步设置:
callSuper:是否输出父类的toString方法,默认为false
includeFieldNames:是否包含字段名称,默认为true
exclude:排除生成tostring的字段
1、生成toString()方法,默认情况下它会按顺序(以逗号分隔)打印你的类名称以及每个字段。
还可以设置不包含哪些字段,可以指定一个也可以指定多个
2、@ToString(exclude = “id”) / @ToString(exclude = {“id”,“name”})
3、如果继承的有父类的话,可以设置callSuper 让其调用父类的toString()方法,例如:@ToString(callSuper = true)
exclude使用:
@ToString(exclude = {"hiredate","job"})
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
}
生成:
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
public Emp() {
}
public String toString() {
return "Emp(empno=" + this.empno + ", ename=" + this.ename + ", mgr=" + this.mgr + ")";
}
}
callSuper:
@ToString(exclude = {"hiredate","job"},callSuper = true)
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
public static void main(String[] args) {
System.out.println(3 + 2);
}
}
生成:
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
public Emp() {
}
public static void main(String[] args) {
System.out.println(5);
}
public String toString() {
return "Emp(super=" + super.toString() + ", empno=" + this.empno + ", ename=" + this.ename + ", mgr=" + this.mgr + ")";
}
}
@EqualsAndHashCode
生成equals和hashCode方法
注意:
默认使用非静态的属性
可以通过exclude参数排除不需要生成的属性
可以通过of参数指定需要生成的属性
它默认不调用父类方法,只使用本类定义的属性进行操作,可以使用callSuper=true来解决,@Data中包含了@EqualsAndHashCode,使用callSuper属性参考@Data
1、
@EqualsAndHashCode
public class Emp {
private Integer empno;
private String ename;
private static String job;
private Integer mgr;
private transient LocalDate hiredate;
}
生成:
public class Emp {
private Integer empno;
private String ename;
private static String job;
private Integer mgr;
private transient LocalDate hiredate;
public Emp() {
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Emp)) {
return false;
} else {
Emp other = (Emp)o;
if (!other.canEqual(this)) {
return false;
} else {
label47: {
Object this$empno = this.empno;
Object other$empno = other.empno;
if (this$empno == null) {
if (other$empno == null) {
break label47;
}
} else if (this$empno.equals(other$empno)) {
break label47;
}
return false;
}
Object this$ename = this.ename;
Object other$ename = other.ename;
if (this$ename == null) {
if (other$ename != null) {
return false;
}
} else if (!this$ename.equals(other$ename)) {
return false;
}
Object this$mgr = this.mgr;
Object other$mgr = other.mgr;
if (this$mgr == null) {
if (other$mgr != null) {
return false;
}
} else if (!this$mgr.equals(other$mgr)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof Emp;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $empno = this.empno;
int result = result * 59 + ($empno == null ? 43 : $empno.hashCode());
Object $ename = this.ename;
result = result * 59 + ($ename == null ? 43 : $ename.hashCode());
Object $mgr = this.mgr;
result = result * 59 + ($mgr == null ? 43 : $mgr.hashCode());
return result;
}
}
2、exclude 排除字段
@EqualsAndHashCode(exclude = {"mgr","hiredate"})
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
}
生成:
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
public Emp() {
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Emp)) {
return false;
} else {
Emp other = (Emp)o;
if (!other.canEqual(this)) {
return false;
} else {
label47: {
Object this$empno = this.empno;
Object other$empno = other.empno;
if (this$empno == null) {
if (other$empno == null) {
break label47;
}
} else if (this$empno.equals(other$empno)) {
break label47;
}
return false;
}
Object this$ename = this.ename;
Object other$ename = other.ename;
if (this$ename == null) {
if (other$ename != null) {
return false;
}
} else if (!this$ename.equals(other$ename)) {
return false;
}
Object this$job = this.job;
Object other$job = other.job;
if (this$job == null) {
if (other$job != null) {
return false;
}
} else if (!this$job.equals(other$job)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof Emp;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $empno = this.empno;
int result = result * 59 + ($empno == null ? 43 : $empno.hashCode());
Object $ename = this.ename;
result = result * 59 + ($ename == null ? 43 : $ename.hashCode());
Object $job = this.job;
result = result * 59 + ($job == null ? 43 : $job.hashCode());
return result;
}
}
of 指定要包含的字段
源代码:
@EqualsAndHashCode(of = {"mgr","hiredate"})
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
}
生成:
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
public Emp() {
}
public static void main(String[] args) {
System.out.println(5);
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Emp)) {
return false;
} else {
Emp other = (Emp)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$mgr = this.mgr;
Object other$mgr = other.mgr;
if (this$mgr == null) {
if (other$mgr != null) {
return false;
}
} else if (!this$mgr.equals(other$mgr)) {
return false;
}
Object this$hiredate = this.hiredate;
Object other$hiredate = other.hiredate;
if (this$hiredate == null) {
if (other$hiredate != null) {
return false;
}
} else if (!this$hiredate.equals(other$hiredate)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof Emp;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $mgr = this.mgr;
int result = result * 59 + ($mgr == null ? 43 : $mgr.hashCode());
Object $hiredate = this.hiredate;
result = result * 59 + ($hiredate == null ? 43 : $hiredate.hashCode());
return result;
}
}
@Data
相当于五个注解:@Getter,@Setter,@ToString,@EqualsAndHashCode,@RequiredArgsConstrutor
@Value
作用于类,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @RequiredArgsConstructor
(注意只有Getter没有Setter)
并且会将字段都变成不可变类型:使用final修饰
代码:
@Value
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private LocalDate hiredate;
}
生成:
public final class Emp {
private final Integer empno;
private final String ename;
private final String job;
private final Integer mgr;
private final LocalDate hiredate;
public Emp(Integer empno, String ename, String job, Integer mgr, LocalDate hiredate) {
this.empno = empno;
this.ename = ename;
this.job = job;
this.mgr = mgr;
this.hiredate = hiredate;
}
public Integer getEmpno() {
return this.empno;
}
public String getEname() {
return this.ename;
}
public String getJob() {
return this.job;
}
public Integer getMgr() {
return this.mgr;
}
public LocalDate getHiredate() {
return this.hiredate;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Emp)) {
return false;
} else {
Emp other = (Emp)o;
Object this$empno = this.getEmpno();
Object other$empno = other.getEmpno();
if (this$empno == null) {
if (other$empno != null) {
return false;
}
} else if (!this$empno.equals(other$empno)) {
return false;
}
label61: {
Object this$ename = this.getEname();
Object other$ename = other.getEname();
if (this$ename == null) {
if (other$ename == null) {
break label61;
}
} else if (this$ename.equals(other$ename)) {
break label61;
}
return false;
}
label54: {
Object this$job = this.getJob();
Object other$job = other.getJob();
if (this$job == null) {
if (other$job == null) {
break label54;
}
} else if (this$job.equals(other$job)) {
break label54;
}
return false;
}
Object this$mgr = this.getMgr();
Object other$mgr = other.getMgr();
if (this$mgr == null) {
if (other$mgr != null) {
return false;
}
} else if (!this$mgr.equals(other$mgr)) {
return false;
}
Object this$hiredate = this.getHiredate();
Object other$hiredate = other.getHiredate();
if (this$hiredate == null) {
if (other$hiredate != null) {
return false;
}
} else if (!this$hiredate.equals(other$hiredate)) {
return false;
}
return true;
}
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $empno = this.getEmpno();
int result = result * 59 + ($empno == null ? 43 : $empno.hashCode());
Object $ename = this.getEname();
result = result * 59 + ($ename == null ? 43 : $ename.hashCode());
Object $job = this.getJob();
result = result * 59 + ($job == null ? 43 : $job.hashCode());
Object $mgr = this.getMgr();
result = result * 59 + ($mgr == null ? 43 : $mgr.hashCode());
Object $hiredate = this.getHiredate();
result = result * 59 + ($hiredate == null ? 43 : $hiredate.hashCode());
return result;
}
public String toString() {
return "Emp(empno=" + this.getEmpno() + ", ename=" + this.getEname() + ", job=" + this.getJob() + ", mgr=" + this.getMgr() + ", hiredate=" + this.getHiredate() + ")";
}
}
@Log
生成log对象,用于记录日志,可以通过topic属性来设置getLogger(String name)方法的参数 例如 @Log4j(topic = “com.xxx.entity.User”),默认是类的全限定名,即 类名.class,log支持以下几种:
@Log java.util.logging.Logger
@Log4j org.apache.log4j.Logger
@Log4j2 org.apache.logging.log4j.Logger
@Slf4j org.slf4j.Logger
@XSlf4j org.slf4j.ext.XLogger
@CommonsLog org.apache.commons.logging.Log
@JBossLog org.jboss.logging.Logger
示例一:
Maven依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
代码:
package com.hc.domain;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Emp {
public static void main(String[] args) {
log.info("info","hahaa");
}
}
生成:
package com.hc.domain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Emp {
private static final Logger log = LoggerFactory.getLogger(Emp.class);
public Emp() {
}
public static void main(String[] args) {
log.info("info", "hahaa");
}
}
结果:

实例二:
代码:
package com.hc.domain;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "com.hc.demo")
public class Emp {
public static void main(String[] args) {
log.info("info","hahaa");
}
}
生成:
package com.hc.domain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Emp {
private static final Logger log = LoggerFactory.getLogger("com.hc.demo");
public Emp() {
}
public static void main(String[] args) {
log.info("info", "hahaa");
}
}
结果:

@SneakyThrows
贴上注解的方法可以省略try-catch
代码:
public class LombokDemo {
@SneakyThrows
public void fun1(){
Thread.sleep(1000);
}
@SneakyThrows(InterruptedException.class)
public void fun2(){
Thread.sleep(1000);
}
}
生成:
public class LombokDemo {
public LombokDemo() {
}
public void fun1() {
try {
Thread.sleep(1000L);
} catch (Throwable var2) {
throw var2;
}
}
public void fun2() {
try {
Thread.sleep(1000L);
} catch (InterruptedException var2) {
throw var2;
}
}
}
@Synchronized
给方法加上同步锁,作用在方法上,自动添加到同步机制,生成的代码并不是直接锁方法而是锁代码块
注意static方法/普通方法/指定lock对象的三种区别
代码:
public class LombokDemo {
@Synchronized
public void fun1() {
System.out.println("fun1");
}
private final Object readLock = new Object();
@Synchronized("readLock")
public void fun2() {
System.out.println("fun1");
}
@Synchronized
public static void fun3() {
System.out.println("fun1");
}
}
生成:
public class LombokDemo {
private final Object $lock = new Object[0];
private static final Object $LOCK = new Object[0];
private final Object readLock = new Object();
public LombokDemo() {
}
public void fun1() {
synchronized(this.$lock) {
System.out.println("fun1");
}
}
public void fun2() {
synchronized(this.readLock) {
System.out.println("fun1");
}
}
public static void fun3() {
synchronized($LOCK) {
System.out.println("fun1");
}
}
}
@Cleanup
用于确保已分配的资源被释放,自动帮我们调用close()方法。比如IO的连接关闭。
主要用来修饰 IO 流相关类, 会在 finally 代码块中对该资源进行 close();
代码:
public class LombokDemo {
public static void fileCopy(File sources, File aim) throws IOException {// psvm
@Cleanup FileInputStream fis = new FileInputStream(sources);
@Cleanup FileOutputStream fos = new FileOutputStream(aim);
byte[] buf = new byte[256];
int len = -1;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
}
}
生成:
public class LombokDemo {
public static void fileCopy(File sources, File aim) throws IOException {// psvm
@Cleanup FileInputStream fis = new FileInputStream(sources);
@Cleanup FileOutputStream fos = new FileOutputStream(aim);
byte[] buf = new byte[256];
int len = -1;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
}
}
@Delegate
为List类型的字段生成一大堆常用的方法,其实这些方法都是List中的方法
源代码:
public class LombokDemo {
@Delegate
private List<String> list ;
}
生成:
public class LombokDemo {
private List<String> list;
public LombokDemo() {
}
public static void main(String[] args) {
}
public int size() {
return this.list.size();
}
public boolean isEmpty() {
return this.list.isEmpty();
}
public boolean contains(Object arg0) {
return this.list.contains(arg0);
}
public Iterator<String> iterator() {
return this.list.iterator();
}
public Object[] toArray() {
return this.list.toArray();
}
public <T> T[] toArray(T[] arg0) {
return this.list.toArray(arg0);
}
public boolean add(String arg0) {
return this.list.add(arg0);
}
public boolean remove(Object arg0) {
return this.list.remove(arg0);
}
public boolean containsAll(Collection<?> arg0) {
return this.list.containsAll(arg0);
}
public boolean addAll(Collection<? extends String> arg0) {
return this.list.addAll(arg0);
}
public boolean addAll(int arg0, Collection<? extends String> arg1) {
return this.list.addAll(arg0, arg1);
}
public boolean removeAll(Collection<?> arg0) {
return this.list.removeAll(arg0);
}
public boolean retainAll(Collection<?> arg0) {
return this.list.retainAll(arg0);
}
public void replaceAll(UnaryOperator<String> arg0) {
this.list.replaceAll(arg0);
}
public void sort(Comparator<? super String> arg0) {
this.list.sort(arg0);
}
public void clear() {
this.list.clear();
}
public String get(int arg0) {
return (String)this.list.get(arg0);
}
public String set(int arg0, String arg1) {
return (String)this.list.set(arg0, arg1);
}
public void add(int arg0, String arg1) {
this.list.add(arg0, arg1);
}
public String remove(int arg0) {
return (String)this.list.remove(arg0);
}
public int indexOf(Object arg0) {
return this.list.indexOf(arg0);
}
public int lastIndexOf(Object arg0) {
return this.list.lastIndexOf(arg0);
}
public ListIterator<String> listIterator() {
return this.list.listIterator();
}
public ListIterator<String> listIterator(int arg0) {
return this.list.listIterator(arg0);
}
public List<String> subList(int arg0, int arg1) {
return this.list.subList(arg0, arg1);
}
public Spliterator<String> spliterator() {
return this.list.spliterator();
}
}
注意:一个类中只能使用一个@Delegate注解,因为使用多个会生成多个size()方法,从而会编译报错。
@Builder
@Builder 是一个非常强大的注解,提供了一种基于建造者模式的构建对象的 API。使用 @Builder 注解为给我们的实体类自动生成 builder() 方法,并且直接根据字段名称方法进行字段赋值,最后使用 build()方法构建出一个实体对象。
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class LombokBuilder {
private int id;
private String name;
}
public class TestMain {
public static void main(String[] args) {
LombokBuilder lombokBuilder = LombokBuilder.builder().id(2).build();
}
}
但是 @Builder 不支持父类字段的生成,当一个实体类存在父类时,@Builder 只能生成当前类的字段构建方法。若需要用到父类的字段方法时, Lombok 提供了新的注解 @SuperBuilder 来应对这种情况,下面是 @SuperBuilder 注解的使用方式。
@SuperBuilder
@SuperBuilder
@Data
public class LombokBuilderParent {
private String value;
}
@Data
@SuperBuilder
public class LombokBuilder extends LombokBuilderParent{
private int id;
private String name;
}
剩余注解总览:
基本注解的使用(注解属性非必选)
@AllArgsConstructor:作用于类,生成参数为所有实例变量的构造函数
@Builder:作用于类,将其变成建造者模式
@Cleanup:作用于变量,自动关闭资源,针对实现了 java.io.Closeable 接口的对象有效
@CustomLog:自定义日志类,生成 log 对象
@Data:作用于类,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
@EqualsAndHashCode:作用于类,覆盖默认的 equals 和 hashCode1
@Generated:用于标记类、变量、方法是自动生成的,没什么大用
@Getter:作用于类,生成该类所有的实例变量的 getter 方法。作用于变量,生成变量的 getter 方法
@NoArgsConstructor:作用于类,生成无参构造方法
@NonNull:作用于成员变量和参数中,标识不能为空,否则抛出空指针异常
@RequiredArgsConstructor:作用于类,生成包含 final 和 @NonNull 注解的成员变量的构造方法
@Setter:作用于类,生成该类所有的实例变量的 setter 方法。作用于变量,生成该变量的 setter 方法
@Singular:作用于集合字段,需要配合 @Builder 使用2
@SneakyThrows:作用于方法,对异常进行捕捉并抛出
@Synchronized:作用于方法,可以替换 synchronized 关键字或 lock 锁
@ToString:作用于类,覆盖默认的 toString() 方法
@val:作用于类、变量,主要用于声明变量的类型,注解将从初始化程序表达式中推断类型,生成的变量是 final 不可以变
@Value:作用于类,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @RequiredArgsConstructor
@var:和 @val 一样,两者区别在于 var 不加 final
@With:作用于类、变量,生成 with + 变量名的方法,返回当前对象
外部注解的使用
@CommonsLog,@Log,@JBossLog,@Log4j,@Log4j2,@Slf4j,@XSlf4j:日志注解,作用于类
实验性注解的使用
@Accessors:类似于 @Builder 支持链式调用,需要配合 @Setter、@Getter 等注解使用,作用于类、变量
@Delegate:作用于容器变量,为该变量生成一堆常用的方法,这些方法都是容器中的方法
@ExtensionMethod:作用于类,向类添加方法,无需创建新的子类
@FieldDefaults:作用于类,定义变量的访问修饰符以及是否加 final
@FieldNameConstants:作用于类,生成一个包含所有成员变量的内部类或者内部枚举,内部类中每个字段值即为字段名并且值不可变
@Helper:作用于方法内部类,使内部类中的方法暴露在外面可以被直接调用,不建议使用
@NonFinal:作用于类、变量,表示变量不加 final
@PackagePrivate:作用于类和变量,相当于访问修饰符的 default,没什么用
@SuperBuilder:支持对于基类成员变量赋值,算是 @Builder 的升级版
@Tolerate:实现对冲突的兼容,作用于方法上,没什么大用,可以配合 @Builder 使用
@UtilityClass:作用于类,将类标记为 final,并且类、内部类中的方法、字段都标记为 static
@WithBy3
基于 v1.18.22 版本的实验性注解
@StandardException:自定义异常类
待完善的
@EqualsAndHashCode.Include(replaces = “”)
@Singular 中的 ignoreNullCollections 属性待完善
@WithBy
优缺点
Lombok 的优缺点
优点:
能通过注解的形式自动生成构造器、getter / setter、equals、hashcode、toString 等方法,提高了一定的开发效率
让代码变得简洁,不用过多的去关注相应的方法
属性做修改时,也简化了维护为这些属性所生成的 getter / setter 方法等
缺点:
不支持多种参数构造器的重载
虽然省去了手动创建一系列方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度
常用
使用lombok最多的地方就是实体类了
@Data
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder (实体类如果有继承慎用)
@Accessors (设置值的链式调用,看个人习惯)
其它常用
@Slf4j (打印日志)
@CleanUp (关闭资源)
Lombok是一个Java库,它通过注解自动为类生成构造函数、getter/setter、equals、hashcode、toString等方法,减少了样板代码。文章详细介绍了Lombok如何利用JSR269API在编译时修改抽象语法树以生成所需方法,以及@NonNull、@Getter、@Setter、@NoArgsConstructor、@AllArgsConstructor、@RequiredArgsConstructor、@ToString、@EqualsAndHashCode、@Data、@Value等注解的用法和示例。此外,还提到了日志注解@Log及其变体,以及@SneakyThrows、@Synchronized等其他实用注解。

2325

被折叠的 条评论
为什么被折叠?



