前言:在日常开发过程中,必定会定义一些DTO(网络协议交互)、Bean(数据库交互)、VO(视图交互)等数据结构来处理业务逻辑。在这些类中,他们的get/set和其他方法与属性数量呈倍数增长,而这些内容是我们日常开发中所不关心重视的。如果你是一名有代码洁癖的Coder一定会非常难以忍受这样的冗余但是必要的代码。这时候Lombok自动代码生成工具一定是你所需要的,当然Lombok功能远远不止这些,不要着急,我接下来会慢慢介绍。
我们先看一个很简单的POJO对象:
public class Worker {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Worker worker = (Worker) o;
return age == worker.age &&
Objects.equals(name, worker.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Worker{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
当你打开这样的类,会不会有些头晕目眩?当然这只是最简单的一个类对象而已。如果这个类有100个属性值,或者前开发者并没有注意格式规范,把属性值混在getter/setter方法中,你会不会更加崩溃?其实仔细观察这些类的方法其实都是一样的,那么就可以抽离出一个模板出来,自动生成这些代码,那就是Lombok做的事。
请看:
@Data
public class Worker {
private String name;
private int age;
}
@Data 这个注解在类上,会自动生成当前类的所有属性的get、set、equal、hashCode、toString方法。
链式风格
当然Lombok的功能远远不止这些,请对比以下的代码,你更喜欢哪一种。
//1 常规写法
Worker worker = new Worker();
worker.setName("木下z");
worker.setAge(18);
//2 链式风格
Worker worker1 = new Worker()
.setName("木下z")
.setAge(18);
相信合理使用这样的链式代码,会更多的程序带来很好的可读性。那如何使用 lombok 使用链式风格呢,请使用 @Accessors(chain = true),看如下代码:
@Data
@Accessors(chain = true)
public class Worker {
private String name;
private int age;
}
这样就完成了一个对于 bean 来讲很友好的链式操作。
静态构造方法
静态构造方法的语义和简化程度真的高于直接去 new 一个对象。比如 new 一个 List 对象,过去的使用是这样的:
List<String> list = new ArrayList<>();
看一下 guava 中的创建方式:
List<String> list = Lists.newArrayList();
那么我们的bean能不能也这样实现呢?答案是可以的。Lombok更改成以下写法。
@Data
@Accessors(chain = true)
@RequiredArgsConstructor(staticName = "of")
public class Worker {
private String name;
private int age;
}
Worker worker = Worker.of().setName("木下z").setAge(18);
当然如果你希望这个对象的某个值必须存在,例如我希望每个Worker都必须有name,那么我只需要
@Data
@Accessors(chain = true)
@RequiredArgsConstructor(staticName = "of")
public class Worker {
@NonNull private String name;
private int age;
}
Worker worker = Worker.of("木下z").setAge(18);
那么我们使用静态方法of构造对象时必须填入制定的参数,否则在编译期就会报错。这样写代码,真的很简洁,而且可读性很强。
Builder模式
构建 bean 的 builder 模式传统是如何实现的。
@Data
public class Worker {
private String name;
private int age;
public static Builder builder(){
return new Builder();
}
public static class Builder{
private String name;
private int age;
public Builder name(String name){
this.name = name;
return this;
}
public Builder age(int age){
this.age = age;
return this;
}
public Worker build(){
Worker worker = new Worker();
worker.setAge(age);
worker.setName(name);
return worker;
}
}
}
Worker worker = Worker.builder().name("木下z").age(18).build();
说实话,这样实现的话,语义化很强、可读性很高,但每一个类都要自己手写一个Builder内部类实在是吃力不讨好。Lombok其实也可以自动帮我们生成这令人头大的代码。请看:
@Data
@Builder
public class Worker {
private String name;
private int age;
}
常用注解
@Setter 注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
@Getter 使用方法同上,区别在于生成的是getter方法。
@ToString 注解在类,添加toString方法。
@EqualsAndHashCode 注解在类,生成hashCode和equals方法。
@NoArgsConstructor 注解在类,生成无参的构造方法。
@RequiredArgsConstructor 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNu注解的字段。
@AllArgsConstructor 注解在类,生成包含类中所有字段的构造方法。
@Data 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@Slf4j 注解在类,生成log变量,严格意义来说是常量。private static final Logger log = LoggerFactory.getLogger(this.class);