https://projectlombok.org/
1 IDEA使用lombok
1.1 IDEA引入lombok插件
1.2 Maven引入lombok
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
provided适合在编译和测试的环境,他和compile很接近,但是provide仅仅需要在编译和测试阶段,provide将不会被打包到lib目录下
2 Lombok实现原理
工作在编译时期
查看编译后的Class文件
IDEA直接在target目录下查看即可
3 Lombok常用注解
3.1 @Getter
Student.java
import lombok.AccessLevel;
import lombok.Getter;
import javax.validation.constraints.NotNull;
/**
* @Getter 为属性生成get方法
* 1.作用在类上:为该类的所有属性都添加Getter方法
* 2.作用在属性上:只为这个属性生成Getter方法
*/
public class Student {
/**
* lazy:作用在final字段上 懒加载(调用getName方法的时候才会去加载)
*/
@Getter(lazy = true)
private final String schoolAddress = "北京市海淀区颐和园路5号";
private String name;
/**
* value:设置访问级别
* onMethod_:为生成的Get方法添加其他的注解
*/
@Getter(
value = AccessLevel.PRIVATE,
onMethod_ = {@NotNull}
)
private Integer age;
}
Student.class
import java.util.concurrent.atomic.AtomicReference;
import javax.validation.constraints.NotNull;
public class Student {
private final AtomicReference<Object> schoolAddress = new AtomicReference();
private String name;
private Integer age;
public Student() {
}
public String getSchoolAddress() {
Object value = this.schoolAddress.get();
if (value == null) {
synchronized(this.schoolAddress) {
value = this.schoolAddress.get();
if (value == null) {
String actualValue = "北京市海淀区颐和园路5号";
value = "北京市海淀区颐和园路5号" == null ? this.schoolAddress : "北京市海淀区颐和园路5号";
this.schoolAddress.set(value);
}
}
}
return (String)((String)(value == this.schoolAddress ? null : value));
}
@NotNull
private Integer getAge() {
return this.age;
}
}
3.2 @Setter
Student.java
import lombok.AccessLevel;
import lombok.Setter;
import javax.validation.constraints.NotNull;
/**
* @Setter 为属性生成set方法
*/
public class Student {
@Setter
private String name;
@Setter(
value = AccessLevel.PRIVATE,
onParam_ = {@NotNull}
)
private Integer age;
}
Student.class
import javax.validation.constraints.NotNull;
public class Student {
private String name;
private Integer age;
public Student() {
}
public void setName(String name) {
this.name = name;
}
private void setAge(@NotNull Integer age) {
this.age = age;
}
}
3.3 @ToString
Student.java
import lombok.Setter;
import lombok.ToString;
import org.junit.Test;
/**
* @ToString 生成toString方法
* 1.作用在类上
* 2.includeFieldNames:是否包含属性名
* 3.exclude:排除属性
* 4.of:指向属性生成(两个都写of>exclude,显示of的)
* 5.callSuper:是否调用父类的toString方法
* 6.doNotUseGetters:true(不会调用get方法来获取属性值,而是通过属性的名字来获取 如果get方法有业务逻辑将不会被触发)
*/
@ToString(
includeFieldNames = false,
//exclude = {"name"},
//of = {"age"},
doNotUseGetters = true
)
public class Student {
@Setter
private String name;
@Setter
private Integer age;
//观察是否调用了这个方法
public Integer getAge() {
System.out.println("调用get方法!");
return this.age;
}
@Test
public void test() {
Student toStringTest = new Student();
toStringTest.setName("小明");
toStringTest.setAge(18);
System.out.println(toStringTest.toString());
}
}
Student.class
import org.junit.Test;
public class Student {
private String name;
private Integer age;
public Student() {
}
public Integer getAge() {
System.out.println("调用get方法!");
return this.age;
}
public String toString() {
return "Student(" + this.name + ", " + this.age + ")";
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Test
public void test() {
Student toStringTest = new Student();
toStringTest.setName("小明");
toStringTest.setAge(18);
System.out.println(toStringTest.toString());
}
}
3.4 @EqualsAndHashCode
Student.java
import lombok.EqualsAndHashCode;
/**
* @EqualsAndHashCode 生成Equals方法和HashCode方法
* 1.作用在类上
* 2.exclude:排除的属性
* 3.of:强制执行的属性
* 4.callSuper:是否调用父类的Equals和HashCode方法
* 5.doNotUseGetters:获取属性值的时候,是否调用属性的get方法
* 6.onParam:生成方法的入参上添加自定义注解
*/
@EqualsAndHashCode(
exclude = {"age"}
)
public class Student {
private String name;
private Integer age;
}
Student.class
public class Student {
private String name;
private Integer age;
public Student() {
}
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 {
Object this$name = this.name;
Object other$name = other.name;
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
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.name;
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
3.5 @Data
Student.java
import lombok.Data;
/**
* @Data 大而全的注解:包含@Getter,@Setter,@ToString,@EqualsAndHashCode
*/
@Data
public class Student {
private String name;
private Integer age;
}
Student.class
public class Student {
private String name;
private Integer age;
public Student() {
}
public String getName() {
return this.name;
}
public Integer getAge() {
return this.age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
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 {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
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;
}
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());
return result;
}
public String toString() {
return "Student(name=" + this.getName() + ", age=" + this.getAge() + ")";
}
}
3.6 @Value
类属性会被编译成final的,因此只有get方法,而没有set方法
import lombok.Value;
@Value
public class Student {
private String name;
private Integer age;
}
public final class Student {
private final String name;
private final Integer age;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public Integer getAge() {
return this.age;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Student)) {
return false;
} else {
Student other = (Student)o;
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
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;
}
return true;
}
}
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());
return result;
}
public String toString() {
return "Student(name=" + this.getName() + ", age=" + this.getAge() + ")";
}
}
3.7 @val
Student.java
import lombok.val;
import java.util.ArrayList;
/**
* @val 弱语言变量
*/
public class Student {
public Student() {
val schoolAddress = "北京市海淀区颐和园路5号";
val students = new ArrayList<>();
students.add("张三");
}
}
Student.class
import java.util.ArrayList;
public class Student {
public Student() {
String schoolAddress = "北京市海淀区颐和园路5号";
ArrayList<Object> students = new ArrayList();
students.add("张三");
}
}
3.8 @NonNull
Student.java
import lombok.NonNull;
/**
* @NonNull 生成非空检查
*/
public class Student {
private String name;
public Student(@NonNull String name) {
this.name = name;
}
}
Student.class
import lombok.NonNull;
public class Student {
private String name;
public Student(@NonNull String name) {
if (name == null) {
throw new NullPointerException("name is marked non-null but is null");
} else {
this.name = name;
}
}
}
3.9 @AllArgsConstructor/@NoArgsConstructor/@RequiredArgsConstructor
Student.java
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* 1.@AllArgsConstructor:全参
* 2.@NoArgsConstructor:无参
* 3.@RequiredArgsConstructor:必要参数
*/
@RequiredArgsConstructor
public class Student {
private final String schoolAddress;
@NonNull
private String name;
private Integer age;
}
Student.class
import lombok.NonNull;
public class Student {
private final String schoolAddress;
@NonNull
private String name;
private Integer age;
public Student(String schoolAddress, @NonNull String name) {
if (name == null) {
throw new NullPointerException("name is marked non-null but is null");
} else {
this.schoolAddress = schoolAddress;
this.name = name;
}
}
}
3.10 @Cleanup
FileUtils.java
import lombok.Cleanup;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @Cleanup 资源关闭
*/
public class FileUtils {
/**
* 文件拷贝
*
* @param in 输入文件路径
* @param out 输出文件路径
*/
public static void copyFile(String in, String out) throws Exception {
@Cleanup FileInputStream fileInputStream = new FileInputStream(in);
@Cleanup FileOutputStream fileOutputStream = new FileOutputStream(out);
int r;
while ((r = fileInputStream.read()) != -1) {
fileOutputStream.write(r);
}
}
public static void main(String[] args) throws Exception {
FileUtils.copyFile(".gitignore",".gitignore-copy");
}
}
FileUtils.class
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Collections;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Collections;
public class FileUtils {
public FileUtils() {
}
public static void copyFile(String in, String out) throws Exception {
FileInputStream fileInputStream = new FileInputStream(in);
try {
FileOutputStream fileOutputStream = new FileOutputStream(out);
int r;
try {
while((r = fileInputStream.read()) != -1) {
fileOutputStream.write(r);
}
} finally {
if (Collections.singletonList(fileOutputStream).get(0) != null) {
fileOutputStream.close();
}
}
} finally {
if (Collections.singletonList(fileInputStream).get(0) != null) {
fileInputStream.close();
}
}
}
public static void main(String[] args) throws Exception {
copyFile(".gitignore", ".gitignore-copy");
}
}
3.11 @Builder
Student.java
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class Student {
private String name;
private Integer age;
}
Student.class
public class Student {
private String name;
private Integer age;
Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public static Student.StudentBuilder builder() {
return new Student.StudentBuilder();
}
public String toString() {
return "Student(name=" + this.name + ", age=" + this.age + ")";
}
public static class StudentBuilder {
private String name;
private Integer age;
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 build() {
return new Student(this.name, this.age);
}
public String toString() {
return "Student.StudentBuilder(name=" + this.name + ", age=" + this.age + ")";
}
}
}
Student stu = new Student
.StudentBuilder()
.age(18)
.build();
//!!! Student(name=null, age=18)
System.out.println(stu);
//Student(name=蔡徐坤, age=58)
Student kunkun = new Student
.StudentBuilder()
.age(58)
.name("蔡徐坤")
.build();
System.out.println(kunkun);
使用默认值
@Builder
@ToString
public class Student {
// 该字段有一个默认值;
private String schoolAddress = "北京市海淀区颐和园路5号";
}
public class Student {
private String schoolAddress = "北京市海淀区颐和园路5号";
Student(String schoolAddress) {
this.schoolAddress = schoolAddress;
}
public static Student.StudentBuilder builder() {
return new Student.StudentBuilder();
}
public String toString() {
return "Student(schoolAddress=" + this.schoolAddress + ")";
}
public static class StudentBuilder {
private String schoolAddress;
StudentBuilder() {
}
public Student.StudentBuilder schoolAddress(String schoolAddress) {
this.schoolAddress = schoolAddress;
return this;
}
public Student build() {
return new Student(this.schoolAddress);
}
public String toString() {
return "Student.StudentBuilder(schoolAddress=" + this.schoolAddress + ")";
}
}
}
// 生成的student对象并没有使用status的默认值
//Student(schoolAddress=北京市海淀区颐和园路5号)
Student student = Student.builder().build();
System.out.println(student);
在StudentBuilder代码的build()方法中可以看出来,生成Student对象时的schoolAddress字段值是StudentBuilder中的schoolAddress字段值。所以如果不通过schoolAddress(String schoolAddress)方法显式的设置schoolAddress字段的话,最终生成的对象中的schoolAddress值是java中String的默认值null,而不是在Student类中规定的默认值北京市海淀区颐和园路5号
@Builder
@ToString
public class Student {
// 该字段有一个默认值;
@Builder.Default
private String schoolAddress = "北京市海淀区颐和园路5号";
}
public class Student {
private String schoolAddress;
// 返回schoolAddress的默认值 北京市海淀区颐和园路5号
private static String $default$schoolAddress() {
return "北京市海淀区颐和园路5号";
}
Student(String schoolAddress) {
this.schoolAddress = schoolAddress;
}
public static Student.StudentBuilder builder() {
return new Student.StudentBuilder();
}
public String toString() {
return "Student(schoolAddress=" + this.schoolAddress + ")";
}
public static class StudentBuilder {
private boolean schoolAddress$set;
private String schoolAddress$value;
StudentBuilder() {
}
public Student.StudentBuilder schoolAddress(String schoolAddress) {
this.schoolAddress$value = schoolAddress;
this.schoolAddress$set = true;
return this;
}
public Student build() {
String schoolAddress$value = this.schoolAddress$value;
// 会判断schoolAddress是否被显式的set,如果没有被set,则使用默认值。
if (!this.schoolAddress$set) {
// 获取Student类中status的默认值1
schoolAddress$value = Student.$default$schoolAddress();
}
return new Student(schoolAddress$value);
}
public String toString() {
return "Student.StudentBuilder(schoolAddress$value=" + this.schoolAddress$value + ")";
}
}
}
可以看到Student类中有一个$default$schoolAddress()的方法,用来返回schoolAddress字段的默认值;然后再看StudentBuilder类,在build()方法的时候会判断是否显式的给status字段赋值,如果没有赋值则将schoolAddress字段设置成默认值
- 如果想让类中的字段默认值生效,需要使用@Default注解
- @Builder会生成一个全参的构造函数
3.12 @Slf4j
SpringBoot项目
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
普通项目
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
@Slf4j
public class Main {
public static void main(String[] args) {
//默认日志级别为info
log.info("info");
log.debug("debug");
log.info("info");
log.error("error");
log.warn("warn");
}
}
离线安装:https://blog.csdn.net/yitian_z/article/details/104134410