Lombok(小辣椒)是一个 Java 库,它通过自动生成样板代码来简化 Java 代码的编写。它提供了一组注解,通过在源代码中添加这些注解,开发人员可以自动创建一些常见的样板代码,如 getter 和 setter 方法、构造函数、equals 和 hashCode 方法等。
使用 Lombok 可以显著减少代码量,提高开发效率,同时还能使代码更加清晰和易读。通过减少样板代码,Lombok 可以使开发人员更专注于业务逻辑的实现,而不必花费太多精力编写重复的代码。
下载
Maven
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
手动
官方网站:https://projectlombok.org/download 直链下载:https://projectlombok.org/downloads/lombok.jar
下载完成后导入到项目即可。
Maven 配置
原理
Lombok是一种插件化注解API,是通过添加注解来实现的,然后在javac进行编译的时候,进行处理。
Java的编译过程可以分成三个阶段:
- 所有源文件会被解析成语法树。
- 调用注解处理器。如果注解处理器产生了新的源文件,新文件也要进行编译。
- 最后,语法树会被分析并转化成类文件。
实际上在上述的第二阶段,会执行lombok.core.AnnotationProcessor,它所做的工作就是我们上面所说的,修改语法树。
使用
@Getter, @Setter
通过在类前添加 @Getter
和 @Setter
可以在编译时自动生成一系列的参数封装函数。但在 IDEA 中若想调用需要安装 Lombok 插件(通常会自带)。
使用注解前:
public class Student {
private String name;
private int age;
private int sno;
public Student(int Sno, String name, int age) {
this.age = age;
this.name = name;
this.sno = Sno;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setSno(int sno) {
this.sno = sno;
}
public int getSno() {
return sno;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
使用注解后:
@Getter
@Setter
public class Student {
private String name;
private int age;
private int sno;
public Student(int Sno, String name, int age) {
this.age = age;
this.name = name;
this.sno = Sno;
}
}
但默认所有参数的set 和 get 方法都是 public。
可以通过设置注解属性来配置,比如全配置为 private:
@Getter(AccessLevel.PRIVATE)
@Setter
public class Student {
private String name;
private int age;
private int sno;
}
也可以在某个参数前单独加一个注解并设置属性:
@Getter
@Setter
public class Student {
private String name;
@Getter(AccessLevel.PRIVATE)
private int age;
private int sno;
}
这样就只有 age 属性无法通过getter访问。
且默认是不会对final
和 static
的变量生成set方法,final
可以生成 get
方法。如果非要给 static
变量生成方法,也可以向上面单独设置权限一样,单独添加一个@Getter
@Accessors
@Accessors
可以给 @Getter
和 @Setter
增加一些特性。
@Target({ElementType.TYPE, ElementType.FIELD}) // 同样支持单独变量设置
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
boolean fluent() default false;
boolean chain() default false;
boolean makeFinal() default false;
String[] prefix() default {};
}
chain
属性默认为 false, 可以通过 @Accessors(chain = true)
设置为 true
。效果是将生成的 get
方法返回一个原对象,这样可以支持链式调用:
Student student = new Student(123, "name", 123);
student
.setSno(213)
.setAge(213);
fluent
属性则可以让生成的 set 方法名字中去掉 set
, 只保留属性名:
Student student = new Student(123, "name", 123);
student
.Sno(213)
.Age(213);
@ArgsConstructor
自动生成构造函数, 有两个版本, @NoArgsConstructor
是生成无参构造函数, @AllArgsConstructor
是生成代参构造函数,参数传入顺序跟声明顺序一致。
还有一个是 @RequiredArgsConstructor
是只会把 final
变量在构造函数中生成。
@ToString
@ToString
注解可以自动生成该类的 toString
方法,默认格式为 类名(属性名=值, 属性名=值...)
。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface ToString {
boolean includeFieldNames() default true;
String[] exclude() default {};
String[] of() default {};
boolean callSuper() default false;
boolean doNotUseGetters() default false;
boolean onlyExplicitlyIncluded() default false;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Exclude {
}
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface Include {
int rank() default 0;
String name() default "";
}
}
其中也可以配置很多属性:
includeFieldNames
默认开启时会输出字段对应的名字:
Student(name=name, age=123, sno=1213)
@ToString(includeFieldNames = false)
关闭后就会省略字段名字:
Student(name, 123, 1213)
exclude
默认为空,表示没有不输出的变量。
@ToString(exclude = {"name", "sno"})
可以设置多个变量不输出:
Student(age=123)
of
跟 exclude 使用方法一样,但是刚好相反,是只保留选择的,其他的省去。
callSuper
会自动在第一项增加调用父类的 toString()
方法:
Student(super=Student@4e50df2e, name=name, age=123, sno=1213)
doNotUseGetters
Lombok 的 toString
方法在访问某个变量的值时, 如果其有 Getter
方法会自动调用,而非直接访问。
将 @ToString(doNotUseGetters = true)
后,访问变量值时就不会再调用 Getter
方法。
Include
可以通过单独设置某个变量的位置和别名:
@ToString.Include(name = "年龄")
Student(name=name, 年龄=123, sno=1213)
@EqualsAndHashCode
自动生成当前类的 equals
和 hashCode
方法。其中 equals
方法默认不会比较父类的属性,因此需要设置 @EqualsAndHashCode(callSuper = true)
才会在 equals
先调用父类的 equals
方法来比较。
@Data
@Data
:该注解包含了 @Getter
、@Setter
、@ToString
、@EqualsAndHashCode
和 @RequiredArgsConstructor
的功能,是一个快捷注解,常用于简化 POJO 类的定义。
@Data
没有更多的控制属性,无法像@EqualsAndHashCode 一样设置调用父类 equals 方法,因此不建议使用的类含有继承关系。
@SneakyThrows
注解在方法中时, 会自动对会报错的部分进行 try-catch 包围。
编译前:
@SneakyThrows
public static void main(String[] args) {
Student student = new Student(1213, "name", 123);
System.out.println(student);
InputStream inputStream = new FileInputStream("1213");
}
编译后:
public static void main(String[] args) {
try {
Student student = new Student(1213, "name", 123);
System.out.println(student);
new FileInputStream("1213");
} catch (Throwable var3) {
throw var3;
}
}
@Cleanup
只能定义在变量前,会在合适的时候自动调用该变量的 close()
方法,通常用于 IO 流。
配合 @SneakyThrows 可以直接实现 try-with-resources
的功能。
@SneakyThrows
public static void main(String[] args) {
Student student = new Student(1213, "name", 123);
System.out.println(student);
@Cleanup
InputStream inputStream = new FileInputStream("1213");
}
编译后:
try {
Student student = new Student(1213, "name", 123);
System.out.println(student);
InputStream inputStream = new FileInputStream("1213");
if (Collections.singletonList(inputStream).get(0) != null) {
inputStream.close();
}
} catch (Throwable var3) {
throw var3;
}
@Builder
:自动生成建造者模式相关的代码,简化对象的创建过程。@Slf4j
:自动为类生成一个名为log
的日志记录器,方便在代码中进行日志输出。
@Log
自动为该类创建 Logger 对象,等价于:
Logger logger = Logger.getLogger(myUserDao.class.getName());
之后使用 log 来调用即可:
@Log
public class Main {
public static void main(String[] args) {
System.out.println("自动生成的Logger名称:"+log.getName());
log.info("我是日志信息");
}
}
可以加上 @Log(topic = "String")
来更改 Logger 名字。