Lombok 项目是一个 Java 库,它会自动插入编辑器和构建工具中,简化 Java 开发。
注解介绍:https://projectlombok.org/api/lombok/package-tree.html
Lombok 本质上就是一个实现了“JSR 269 API”的程序。在使用 javac 的过程中,它产生作用的具体流程如下:
javac 对源代码进行分析,生成了一棵抽象语法树(AST)
运行过程中调用实现了“JSR 269 API”的 Lombok 程序
此时 Lombok 就对第一步骤得到的 AST 进行处理,找到 @Data 注解所在类对应的语法树(AST),然后修改该语法树(AST),增加 getter 和 setter 方法定义的相应树节点
javac 使用修改后的抽象语法树(AST)生成字节码文件,即给 class 增加新的节点(代码块)
通过读 Lombok 源码,发现对应注解的实现都在 HandleXXX 中,比如 @Getter 注解的实现在HandleGetter.handle() 。还有一些其它类库使用这种方式实现,比如 Google Auto、Dagger 等等。
1. 添加 maven 依赖
org.projectlombok
lombok
1.18.4
provided
2. 安装 lombok 插件(idea 为例)
File --> Settings --> Plugins --> 搜索 Lombok --> Install
插件下载地址1:http://plugins.jetbrains.com/plugin/6317-lombok-plugin
插件下载地址2:https://github.com/mplushnikov/lombok-intellij-plugin/releases
File --> Settings --> Plugins --> Install Plugin from Disk… --> 选择插件包
3. 解决编译出错问题
编译时出错,可能是没有 enable 注解处理器。
File --> Settings --> Annotation Processors --> 勾上 Enable annotation processing
val:用在局部变量前,将从初始化表达式推断出类型,本地变量也将成为 final 变量。不能用于字段,初始化表达式是必需的。
val example = new ArrayList<String>();
example.add("Hello, World!");
val foo = example.get(0);
var:用在局部变量前,和 val 唯一的区别是不会变为 final 。
@NonNull:用在方法或构造函数的参数上,会自动在方法内对该参数进行是否为空的校验(null-check),如果为空,则抛出 NullPointerException 。
public NonNullExample(@NonNull Person person) {
if (person == null) {
throw new NullPointerException("person is marked @NonNull but is null");
}
}
@Cleanup:用在局部变量上,在当前变量范围内即将执行完毕退出之前会清理资源,自动生成 try-finally 这样的代码来关闭流。
public static void main(String[] args) throws IOException {
@Cleanup
InputStream in = new FileInputStream(args[0]);
@Cleanup
OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[1024];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
@Getter/@Setter:用在类上,为所有字段生成 getter/setter 方法;用在字段上,只为该字段生成 getter/setter 方法。默认为 public,可以通过 AccessLevel 属性设置逻辑访问级别为 public、protected、package、和 private 。AccessLevel.NONE 访问级别手动禁用任何字段的 getter/setter生成。
如果字段名为 isFoo,字段类型为 boolean,那么生成方法为 getFoo 和 setFoo 。
要在生成的方法上添加注释,可以使用 onMethod=@__({@AnnotationsHere}); 要将注释放在生成的setter 方法的唯一参数上。
// 如果设置为true,则为boolean字段生成的getter将使用get前缀而不是默认is前缀
// 并且任何生成的调用getter的代码(例如)@ToString也将使用get而不是is。
lombok.getter.noIsPrefix = [true | false] (default: false)
@ToString:用在类上,可以自动覆写 toString 方法。默认情况下,会按顺序打印您的类名以及每个字段,并以逗号分隔。可以使用 exclude 属性排除某些字段,callSuper 属性调用父类字段。
@EqualsAndHashCode:用在类上,自动生成 equals 方法和 hashCode 方法。默认情况下,它将使用所有非静态,非瞬态字段。使用 exclude 属性排除某些字段,callSuper 属性调用父类字段。
@NoArgsConstructor、@RequiredArgsConstructor、@AllArgsConstructor:用在类上,自动生成无参构造函数、使用所有参数的构造函数、把所有 @NonNull 属性或者 final 字段作为参数的构造函数。
使用 staticName 属性设置构造函数名,则生成的构造函数将是私有的,并且用包裹真实构造函数的相同参数列表生成一个额外的静态“构造函数”。
@Data:用在类上,相当于同时使用了 @ToString、@EqualsAndHashCode、@Getter、@Setter和 @RequiredArgsConstrutor 。使用 staticConstructor 属性设置一个构造函数名,则生成的构造函数将是私有的,并且用包裹真实构造函数的相同参数列表生成一个额外的静态“构造函数”。
@Value:用在类上,是 @Data 的不可变形式,相当于同时使用了 @ToString、@EqualsAndHashCode、@Getter、@FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) 和 @AllArgsConstructor。
@Builder:用在类、构造器、方法上,为你提供复杂的builder APIs 。
@Builder
class Example<T> {
private T foo;
private final String bar;
}
// after
class Example<T> {
private T foo;
private final String bar;
private Example(T foo, String bar) {
this.foo = foo;
this.bar = bar;
}
public static <T> ExampleBuilder<T> builder() {
return new ExampleBuilder<T>();
}
public static class ExampleBuilder<T> {
private T foo;
private String bar;
private ExampleBuilder() {}
public ExampleBuilder foo(T foo) {
this.foo = foo;
return this;
}
public ExampleBuilder bar(String bar) {
this.bar = bar;
return this;
}
@java.lang.Override public String toString() {
return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")";
}
public Example build() {
return new Example(foo, bar);
}
}
}
@SneakyThrows:自动抛受检异常,而无需显式在方法上使用throws语句。
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}
@Synchronized:用在方法上,它的操作类似于synchronized关键字,但它锁定在不同的对象上。
@Synchronized
public static void hello() {
System.out.println("world");
}
//相当于
private static final Object $LOCK = new Object[0];
public static void hello() {
synchronized ($LOCK) {
System.out.println("world");
}
}
@Log:根据不同的注解生成不同类型的 log 对象,实例名称都是 log,有六种可选实现类。