lombok

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字段设置成默认值

  1. 如果想让类中的字段默认值生效,需要使用@Default注解
  2. @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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值