简化你的开发-使用lombok
Java 最使人诟病的地方,莫过于随处都有的 Getter/Setter 了;但是现在,lombok 为我们解决了这一难题。本次教程,就带大家认识 lombok,并且使用它来简化我们的 Java 开发。
集成 lombok
1. 添加 Maven 依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
2. 安装IDE插件(此处以 Intellij 为例)
依次点击 File -> Settings -> Plugins -> Browse repositories
, 在搜索框中搜索 lombok
并安装即可。
快速使用
lombok 为我们提供了以下的注解用于简化开发:
@Getter 用于生成 getter 方法
@Setter 用于生成 setter 方法
- @NoArgsConstructor 生成无参构造方法
- @AllArgsConstructor 使用所有域生成构造方法
- @RequiredArgsConstructor 将根据使用了
final
进行修饰的域或是使用了类似于@NonNull
进行修饰的域生成构造方法 - @ToString 根据相关属性生成类
Json
格式的toString
方法 - @EqualsAndHashCode 生成
equals
和对应的hashCode
方法 - @Builder 使用构造器模式生成
build
方法 - @Default 配合
@Builder
使用 - @Value 生成不可变对象
- @Data 组合注解,结合了
@Getter, @Setter, @RequiredArgsConstructor ,@ToString @EqualsAndHashCode @Value
- @NonNull 使用此注解的属性,
lombok
将自动进行空值检查 - @Cleanup 在做文件流(或是其他资源)相关操作时,使用此注解,不管是否发生了异常,都可自动关闭流
- @Synchronized 等同于
synchronized
关键字 - @SneakyThrows 使用此注解,可自动将异常包装成 RuntimeException 并抛出,无需手动写
try{}cache(){}
注意
此处有几点需要注意:
- 当我们需要使用构造器模式时,如果需要自行初始化变量,请记得添加
@Default
注解,否则 lombok 会忽略初始值,并根据默认设置进行变量赋值 @AllArgsConstructor
@EqualsAndHashCode
需要慎重使用,否则可能导致一些意外情况
示例
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
@EqualsAndHashCode
public class Student {
@NonNull
private String name;
private Integer age;
@Default
private List<String> courses = new ArrayList<>();
}
测试
public class StudentTest {
@Test
public void testLombok() throws Exception {
Student student = Student.builder().name("Tom").build();
student.setAge(17);
System.out.println(student.getName()+" is "+ student.getAge() +" years old");
}
}
让我们反编译 lombok 生成的class文件,看看 lombok 到底做了些什么:
public class Student {
@NonNull
private String name;
private Integer age;
private List<String> courses;
private static List<String> $default$courses() {
return new ArrayList();
}
public static Student.StudentBuilder builder() {
return new Student.StudentBuilder();
}
@NonNull
public String getName() {
return this.name;
}
public Integer getAge() {
return this.age;
}
public List<String> getCourses() {
return this.courses;
}
public void setName(@NonNull String name) {
if (name == null) {
throw new NullPointerException("name");
} else {
this.name = name;
}
}
public void setAge(Integer age) {
this.age = age;
}
public void setCourses(List<String> courses) {
this.courses = courses;
}
public Student() {
}
@ConstructorProperties({"name", "age", "courses"})
public Student(@NonNull String name, Integer age, List<String> courses) {
if (name == null) {
throw new NullPointerException("name");
} else {
this.name = name;
this.age = age;
this.courses = courses;
}
}
public String toString() {
return "Student(name=" + this.getName() + ", age=" + this.getAge() + ", courses=" + this.getCourses() + ")";
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Student)) {
return false;
} else {
Student other = (Student)o;
if (!other.canEqual(this)) {
return false;
} else {
label47: {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name == null) {
break label47;
}
} else if (this$name.equals(other$name)) {
break label47;
}
return false;
}
Object this$age = this.getAge();
Object other$age = other.getAge();
if (this$age == null) {
if (other$age != null) {
return false;
}
} else if (!this$age.equals(other$age)) {
return false;
}
Object this$courses = this.getCourses();
Object other$courses = other.getCourses();
if (this$courses == null) {
if (other$courses != null) {
return false;
}
} else if (!this$courses.equals(other$courses)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof Student;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
Object $age = this.getAge();
result = result * 59 + ($age == null ? 43 : $age.hashCode());
Object $courses = this.getCourses();
result = result * 59 + ($courses == null ? 43 : $courses.hashCode());
return result;
}
public static class StudentBuilder {
private String name;
private Integer age;
private boolean courses$set;
private List<String> courses;
StudentBuilder() {
}
public Student.StudentBuilder name(String name) {
this.name = name;
return this;
}
public Student.StudentBuilder age(Integer age) {
this.age = age;
return this;
}
public Student.StudentBuilder courses(List<String> courses) {
this.courses = courses;
this.courses$set = true;
return this;
}
public Student build() {
return new Student(this.name, this.age, this.courses$set ? this.courses : Student.$default$courses());
}
public String toString() {
return "Student.StudentBuilder(name=" + this.name + ", age=" + this.age + ", courses=" + this.courses + ")";
}
}
}
通过反编译class文件,我们可以清楚的看到源码中同样生成了 get/set/build 等方法,只不过由之前自己手工编写变成了 lombok 帮我们生成对应的方法。