Lombok注解速查

Lombok一个帮你写代码的神器,具体介绍请移步Lombok官网

使用步骤:

  1. Idea 安装 Lombok 插件
  2. Maven 引入
<!-- lombok依赖  -->
<dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>1.18.16</version>
     <scope>provided</scope>
</dependency>

Lombok的scope=provided,说明它只在编译阶段生效,不需要打入包中。事实正是如此,Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件。

3.使用 lomback 注解

1. @Getter and @Setter

使用@Getter@Setter注释任何字段,以使lombok自动生成默认的getter / setter
默认的getter只是返回该字段,如果该字段被称为foo,则名为getFoo(如果该字段的类型为boolean,则为isFoo)。
默认生成的 getter / setter方法是公共的,你可以指定一个AccessLevel来设置访问级别。访问级别有PUBLICPROTECTEDPACKAGEPRIVATE四种。
你还可以在类上添加@Getter@Setter注解。在这种情况下,就好像你使用该注解来注释该类中的所有非静态字段一样。
你始终可以使用特殊的AccessLevel.NONE访问级别来手动禁用任何字段的getter / setter生成。这时你可以覆盖类上的@Getter@Setter@Data注释的行为。

使用 Lombok Java 代码:

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class GetterSetterExample {
    @Getter(AccessLevel.NONE)
    private String code;
    @Getter(AccessLevel.PROTECTED)
    private boolean success;
}

编译后:

public class GetterSetterExample {

    private String code;
    private boolean success;

    public void setCode(final String code) {
        this.code = code;
    }

    public void setSuccess(final boolean success) {
        this.success = success;
    }

    protected boolean isSuccess() {
        return this.success;
    }
}

2. @ToString

生成toString()方法的实现。
默认情况下,它将使用所有非静态字段

属性描述
includeFieldNames打印时是否显示字段名称,默认为 true
of打印字段;如果存在,只会打印标识的字段
exclude跳过字段;和of相反;不会打印标识的字段。 也可以在字段上使用 @ToString.Exclude跳过。
callSupertoString是否包含超类实现的结果,默认为 false
doNotUseGetters默认为 false;如果值为true,则Lombok会直接获取 field 而不是通过get方法获取值

使用 Lombok Java 代码:

import lombok.ToString;

@ToString(callSuper = true)
public class ToStringExample extends GetterSetterExample {
    private static final int STATIC_VAR = 10;
    private String name;
    @ToString.Exclude
    private int id;
}

编译后:

public class ToStringExample extends GetterSetterExample {

    private static final int STATIC_VAR = 10;
    private String name;
    private int id;

    public ToStringExample() {
    }

    public String toString() {
        return "ToStringExample(super=" + super.toString() + ", name=" + this.name + ")";
    }
}

3. @EqualsAndHashCode

生成equals(Object other)hashCode()方法的实现。
默认情况下,它将使用所有非静态,非瞬态字段。

属性描述
of打印字段;如果存在,只会包含标识的字段
exclude跳过字段;和of相反;不会包含标识的字段。 也可以在字段上使用 @EqualsAndHashCode.Exclude跳过。
callSuperequals/hashCode是否包含超类实现的结果,默认为 false
doNotUseGetters默认为 false;如果值为true,则Lombok会直接获取 field 而不是通过get方法获取值(如果可用)

使用 Lombok Java 代码:

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(callSuper = true, exclude = {"name"})
public class EqualsAndHashCodeExample extends GetterSetterExample {

    private static final int STATIC_VAR = 10;
    private int id;
    private String name;
}

编译后:

public class EqualsAndHashCodeExample extends GetterSetterExample {

    private static final int STATIC_VAR = 10;
    private int id;
    private String name;

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof EqualsAndHashCodeExample)) {
            return false;
        } else {
            EqualsAndHashCodeExample other = (EqualsAndHashCodeExample)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (!super.equals(o)) {
                return false;
            } else {
                return this.id == other.id;
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof EqualsAndHashCodeExample;
    }

    public int hashCode() {
        int PRIME = true;
        int result = super.hashCode();
        result = result * 59 + this.id;
        return result;
    }
}

4. @AllArgsConstructor、@RequiredArgsConstructor、@NoArgsConstructor

生成构造函数

属性描述
access设置构造器的权限。
staticName如果生成静态的构造方法,那么原来的实例构造方法将会被私有(private),然后创建一个你指定名称的静态构造方法,并且是public的
注解描述
@AllArgsConstructor生成一个包含所有变量的构造函数。 参数顺序与属性顺序一致。 标有@NonNull的字段会进行非空校验。
@NoArgsConstructor生成没有参数的构造函数。
当类中有final字段没有被初始化时,编译器会报错,但是也可用@NoArgsConstructor(force = true)将所有final字段都将初始化为0/false/null。 对于具有约束的字段(例如@NonNull字段),不会生成任何检查。
@RequiredArgsConstructor会生成一个无参构造方法或者一个包含以final修饰的未经初始化的字段以及标识了@NotNull的变量的有参构造方法。

使用 Lombok Java 代码:

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor(staticName = "myCustom")
public class ConstructorExample {
    private static final int STATIC_VAR = 10;
    private int id;
    private String name;
}

编译后:

public class ConstructorExample {

    private static final int STATIC_VAR = 10;
    private int id;
    private String name;

    public ConstructorExample(final int id, final String name) {
        this.id = id;
        this.name = name;
    }

    private ConstructorExample() {
    }

    public static ConstructorExample myCustom() {
        return new ConstructorExample();
    }
}

使用 Lombok Java 代码:

import lombok.RequiredArgsConstructor;
import lombok.NonNull;

@RequiredArgsConstructor
public class RequiredArgsConstructorExample {
    private final int id;
    @NonNull
    private String name;
}

编译后:

public class RequiredArgsConstructorExample {

    private final int id;
    @NonNull
    private String name;

    public ConstructorExample(final int id, @NonNull final String name) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            this.id = id;
            this.name = name;
        }
    }
}

5. @Data

@Data@ToString@EqualsAndHashCode@Getter@Setter@RequiredArgsConstructor五个注解的集合。

使用 Lombok Java 代码:

import lombok.Data;

@Data 
public class DataExample {
    private static final int STATIC_VAR = 10;
    private int id;
    private String name;
}

编译后:

public class DataExample {

    private static final int STATIC_VAR = 10;
    private int id;
    private String name;

    public DataExample() {
    }

    public int getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public void setId(final int id) {
        this.id = id;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof DataExample)) {
            return false;
        } else {
            DataExample other = (DataExample)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (this.getId() != other.getId()) {
                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;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof DataExample;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + this.getId();
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public String toString() {
        return "DataExample(id=" + this.getId() + ", name=" + this.getName() + ")";
    }
}

6. @Value

@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。

7. @Builder

构建者模式 只能标注到类上,将生成类的一个当前流程的一种链式构造工厂,如下:

BuilderExample builderExample = BuilderExample.builder().name("路飞").listAdd("你好").build();
System.out.println(builderExample.toString());

运行输出:

BuilderExample(id=1, name=路飞, list=[你好])

常配合@Singular注解使用,@Singular注解使用在jdk内部集合类型的属性,Map类型的属性以及Guava的com.google.common.collect 的属性上。
例如 未标注@Singular的属性,一般setter时,会直接覆盖原来的引用,标注了@Singular的属性,集合属性支持添加操作,会在属性原来的基础上增加。
使用@Builder.Default来设置默认值

使用 Lombok Java 代码:

import lombok.Builder;
import lombok.ToString;
import lombok.Singular;
import java.util.Set;

@Builder
@ToString
public class BuilderExample {
    @Builder.Default
    private final int id = 1;
    private final String name;
    @Singular("listAdd")
    private final List<String> list;
}

编译后:

public class BuilderExample {

    private final int id;
    private final String name;
    private final List<String> list;

    private static int $default$id() {
        return 1;
    }

    BuilderExample(final int id, final String name, final List<String> list) {
        this.id = id;
        this.name = name;
        this.list = list;
    }

    public static BuilderExample.BuilderExampleBuilder builder() {
        return new BuilderExample.BuilderExampleBuilder();
    }

    public String toString() {
        return "BuilderExample(id=" + this.id + ", name=" + this.name + ", list=" + this.list + ")";
    }

    public static class BuilderExampleBuilder {
        private boolean id$set;
        private int id$value;
        private String name;
        private ArrayList<String> list;

        BuilderExampleBuilder() {
        }

        public BuilderExample.BuilderExampleBuilder id(final int id) {
            this.id$value = id;
            this.id$set = true;
            return this;
        }

        public BuilderExample.BuilderExampleBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public BuilderExample.BuilderExampleBuilder listAdd(final String listAdd) {
            if (this.list == null) {
                this.list = new ArrayList();
            }

            this.list.add(listAdd);
            return this;
        }

        public BuilderExample.BuilderExampleBuilder list(final Collection<? extends String> list) {
            if (list == null) {
                throw new NullPointerException("list cannot be null");
            } else {
                if (this.list == null) {
                    this.list = new ArrayList();
                }

                this.list.addAll(list);
                return this;
            }
        }

        public BuilderExample.BuilderExampleBuilder clearList() {
            if (this.list != null) {
                this.list.clear();
            }

            return this;
        }

        public BuilderExample build() {
            List list;
            switch(this.list == null ? 0 : this.list.size()) {
            case 0:
                list = Collections.emptyList();
                break;
            case 1:
                list = Collections.singletonList(this.list.get(0));
                break;
            default:
                list = Collections.unmodifiableList(new ArrayList(this.list));
            }

            int id$value = this.id$value;
            if (!this.id$set) {
                id$value = BuilderExample.$default$id();
            }

            return new BuilderExample(id$value, this.name, list);
        }

        public String toString() {
            return "BuilderExample.BuilderExampleBuilder(id$value=" + this.id$value + ", name=" + this.name + ", list=" + this.list + ")";
        }
    }
}

8. @Accessors

链式风格 @Accessors注解用于配置lombok如何生成getter和setter。

属性描述
fluent默认false;设置为true时getter和setter方法将省略get和set前缀,且setter方法返回当前对象
chain默认false;设置为true时setter方法返回当前对象
prefix用于设置生成getter和setter方法的字段名会忽视指定前缀(属性必须为驼峰式命名
new AccessorsExample().id(1).name("路飞");

使用 Lombok Java 代码:

@Getter
@Setter
@Accessors(fluent = true, prefix = "a")
public class AccessorsExample {
    private int aId;
    private String aName;
}

编译之后为:

public class AccessorsExample {

    private int aId;
    private String aName;

    public AccessorsExample() {
    }

    public int id() {
        return this.aId;
    }

    public String name() {
        return this.aName;
    }

    public AccessorsExample id(final int aId) {
        this.aId = aId;
        return this;
    }

    public AccessorsExample name(final String aName) {
        this.aName = aName;
        return this;
    }
}

9. @Slf4j、@Log4j2

在需要打印日志的类中使用,项目中使用slf4j、log4j2日志框架
相当于:

private  final Logger log = LoggerFactory.getLogger(当前类名.class);

10. @NonNull

该注解快速判断是否为空,为空抛出java.lang.NullPointerException。

11. @Synchronized

注解自动添加到同步机制,生成的代码并不是直接锁方法,而是锁代码块, 作用范围是方法上。

12. @Cleanup

注解用于确保已分配的资源被释放(IO的连接关闭)。