优雅的代码生成工具Lombok

859 阅读4分钟

前言:在日常开发过程中,必定会定义一些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);

参考资料

小瓜哥 你见过哪些目瞪口呆的 Java 代码技巧?