# lombok
# 原理
# @Data
该注解同时包含以下注解:相当于一个注解集合
@Getter
@Setter
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
# 默认不调用父类的@EqualsAndHashCode
如果@Data注解的类存在父类,默认在equals方法中不会调用父类的equals。(HashCode同理)
通常IDEA会给出警告提示:
Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '(callSuper=false)' to your type.
此时给类加上@EqualsAndHashCode(callSuper = true)注解即可解决,因为通常类的比较需要用所有属性。
# 使用@Data同时再使用其包含的注解子集,会覆盖其相应功能
如果再使用
@ToString(callSuper = true)注解,则会覆盖@Data的@ToString
# @ToString
// 生成的toString方法中是否包含字段名称
boolean includeFieldNames() default true;
// 排除哪些字段
String[] exclude() default {};
// 指定只打印哪些字段
String[] of() default {};
// 是否调用父类的toString方法,作为当前类toString的一部分。
boolean callSuper() default false;
// 默认调用field的getter方法
boolean doNotUseGetters() default false;
// 只包含显式指定@ToString.Include的字段
boolean onlyExplicitlyIncluded() default false;
// 不包含此注解的字段
public @interface Exclude {}
// 可用于方法或者field
// method:包含方法的返回值
// field:包含此字段
public @interface Include {
// 指定打印优先级,值越大越优先
int rank() default 0;
// 要在生成的{@code toString()}中显示的名称,此外,如果此批注位于方法上,并且名称与现有字段匹配,则会替换该字段。
String name() default "";
}
# 如何使用@builder
# 引入lombok依赖
# 在类上标记@builder
# 最好类同时加上@AllArgsConstructor(access = AccessLevel.PRIVATE)
只加@builder, 生成的代码, 包含的构造器是default的, 也就是没有任何修饰的, 能被同包中类创建, 因此加上此注解后, 便无法直接创建此类实例, 必须通过构建器模式创建.
# 如何使用
直接使用
类名.builder()创建一个构造器类, 然后通过构造器类设置属性, 最后build()生成本类.
//示例
Person.PersonBuilder builder = Person.builder().id(15).name("jesse");
//每一次调用build()都会生成一个新的不可变的实例
Person p = builder.build();
//builder构建实例, 可以重复调用
# 何时该使用构建器模式
创建类实例, 一般有3种做法:
- 使用构造函数
- 使用java bean方式(set方式)
- 构建器模式
创建类实例时, 其
属性很多, 并且属性的组合也很多(说明参数基本都是可选的), 如果使用构造函数的话, 会重载很多次构造函数, 而java bean的方式不方便进行链式调用, 此时使用构建器模式就相当合适了.
# 实现原理
其实就是帮你实现了builder(构建器)设计模式, 反编译后的代码在下面, 一看就懂了, 不懂就得去了解一下设计模式了.
# 反编译前
@builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Person {
private Integer id;
private String name;
}
# 反编译后
public class Person {
private Integer id;
private String name;
private Person(final Integer id, final String name) {
this.id = id;
this.name = name;
}
public static Person.PersonBuilder builder() {
return new Person.PersonBuilder();
}
public static class PersonBuilder {
private Integer id;
private String name;
PersonBuilder() {
}
public Person.PersonBuilder id(final Integer id) {
this.id = id;
return this;
}
public Person.PersonBuilder name(final String name) {
this.name = name;
return this;
}
public Person build() {
return new Person(this.id, this.name);
}
public String toString() {
return "Person.PersonBuilder(id=" + this.id + ", name=" + this.name + ")";
}
}
}
# @data
这里是准备说一些关于lombok的注意事项, 因为它有些坑是不太明显的, 但有时会造成比较大的问题, 排查lombok相关问题, 主要通过查看编译后的文件来解决.
在使用@data时, lombok会帮你生成
equals()和hashcode()方法, 这是很多人都不清楚的,equals()中它会帮你针对每一个field去比较, 但是请注意, 它不会帮你比较父类中的field, 因此在使用时可能会出现莫名其妙的问题.
# 场景重现
为了说明上面描述的这个问题, 下面以Person和Son两个类来说明
父类
@Data
public class Person {
private String name;
private int age;
}
子类
@Data
public class Son extends Person {
private String toy;
}
测试类
测试方法中s1和s2两者的toy值相等
# @SneakyThrows
https://www.jianshu.com/p/f33e3ca7f102
← lambda用法归总 mybatis入门 →