Lombok 常规操作

前言

官方文档

@RequiredArgsConstructor

可以用在类上,使用类中所有带有 @NonNull 注解的或者带有 final 修饰的成员变量生成对应的构造方法

编写优雅的 Spring 依赖注入代码:

1
2
3
4
5
6
7
8
@RequiredArgsConstructor(onConstructor=@__(@Autowired))
public class PunchclockService {
private final OkHttpClient okHttpClient;
...
}

@AllArgsConstructor

可以用在类上,为类提供一个全参的构造方法

@NoArgsConstructor

可以用在类上,为类提供一个无参的构造方法

@NonNull

可以在方法或构造函数的参数上使用 @NonNulllombok 为生成 null-check 语句。

编译前:

1
2
3
4
5
6
7
8
9
10
import lombok.NonNull;
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
this.name = person.getName();
}
}

编译后:

1
2
3
4
5
6
7
8
9
10
11
12
13
import lombok.NonNull;
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
if (person == null) {
throw new NullPointerException("person is marked @NonNull but is null");
}
this.name = person.getName();
}
}

@Cleanup

可以使用 @Cleanup 确保在代码执行路径退出当前作用域之前自动清除给定资源

编译前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
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[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}

编译后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (out != null) {
out.close();
}
}
} finally {
if (in != null) {
in.close();
}
}
}
}

如果要清理的对象类型没有 close() 方法,而是其他一些无参数方法,则可以指定此方法的名称,如下所示:

1
@Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);

不能通过@Cleanup调用带有1个或多个参数的清理方法。

@Getter and @Setter

可以使用 @Getter/@Setter 注释任何字段,让 lombok 自动生成默认的 getter / setter, 也可以注释整个类

编译前:

1
2
3
4
5
6
7
public class Person {
@Getter @Setter private int age = 1;
@Setter(AccessLevel.PROTECTED) private String name;
}

编译后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Person {
private int age = 10;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
protected void setName(String name) {
this.name = name;
}
}

@ToString

任何类定义都可以用 @ToString 注释,让 lombok 生成 toString() 方法的实现

编译前:

1
2
3
4
@ToString
public class ToStringExample {
private String name;
}

编译后:

1
2
3
4
5
6
7
@ToString
public class ToStringExample {
private String name;
@Override public String toString() {
return "ToStringExample(" + this.getName() + ")";
}
}

@EqualsAndHashCode

任何类定义都可以用 @EqualsAndHashCode 注释,生成 equalscanEqualhashCode

@Data

可以使用 @Data 作用在类上,生成 @ToString + @EqualsAndHashCode + @Getter / @Setter

@Value

可以使用 @Value 作用在类上,会生成含所有参数的构造方法 + @Getter + @ToString + @EqualsAndHashCode 方法

@Builder

可以使用 @Builder 作用在类上,生成复杂的构建器API

编译前:

1
2
3
4
5
6
7
@Builder
public class BuilderExample {
@Builder.Default private long created = System.currentTimeMillis();
private String name;
private int age;
@Singular private Set<String> occupations;
}

编译后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class BuilderExample {
private long created;
private String name;
private int age;
private Set<String> occupations;
BuilderExample(String name, int age, Set<String> occupations) {
this.name = name;
this.age = age;
this.occupations = occupations;
}
private static long $default$created() {
return System.currentTimeMillis();
}
public static BuilderExampleBuilder builder() {
return new BuilderExampleBuilder();
}
public static class BuilderExampleBuilder {
private long created;
private boolean created$set;
private String name;
private int age;
private java.util.ArrayList<String> occupations;
BuilderExampleBuilder() {
}
public BuilderExampleBuilder created(long created) {
this.created = created;
this.created$set = true;
return this;
}
public BuilderExampleBuilder name(String name) {
this.name = name;
return this;
}
public BuilderExampleBuilder age(int age) {
this.age = age;
return this;
}
public BuilderExampleBuilder occupation(String occupation) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.add(occupation);
return this;
}
public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.addAll(occupations);
return this;
}
public BuilderExampleBuilder clearOccupations() {
if (this.occupations != null) {
this.occupations.clear();
}
return this;
}
public BuilderExample build() {
// complicated switch statement to produce a compact properly sized immutable set omitted.
Set<String> occupations = ...;
return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
}
@java.lang.Override
public String toString() {
return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
}
}
}

@SneakyThrows

在实际开发中 @SneakyThrows 不够灵活,但是在一些确定不太可能发生异常的地方但是又必须 cache checked exception 的地方,可以提高代码的可读性。

编译前:

1
2
3
4
5
6
public class SneakyThrowsExample implements Runnable {
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}
}

编译后:

1
2
3
4
5
6
7
8
9
public class SneakyThrowsExample implements Runnable {
public String utf8ToString(byte[] bytes) {
try {
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw Lombok.sneakyThrow(e);
}
}
}

@Synchronized

官方解释:
@Synchronizedsynchronized 方法修饰符的更安全的变体。与 synchronized 一样,注释只能用于静态和实例方法。@Synchronized 的操作类似于 synchronized 关键字,但它锁定在不同的对象上。
关键字 synchronized 锁定 this ,但 @Synchronized 锁定在名为 $lock 的字段上,并且该字段是私有的。(如果该字段不存在,则会为你创建该字段。)如果注释静态方法,则注释会锁定名为 $LOCK 的静态字段。

编译前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SynchronizedExample {
private final Object readLock = new Object();
@Synchronized
public static void hello() {
System.out.println("world");
}
@Synchronized
public int answerToLife() {
return 42;
}
@Synchronized("readLock")
public void foo() {
System.out.println("bar");
}
}

编译后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class SynchronizedExample {
private static final Object $LOCK = new Object[0];
private final Object $lock = new Object[0];
private final Object readLock = new Object();
public static void hello() {
synchronized($LOCK) {
System.out.println("world");
}
}
public int answerToLife() {
synchronized($lock) {
return 42;
}
}
public void foo() {
synchronized(readLock) {
System.out.println("bar");
}
}
}

@Log相关

@CommonsLog
1
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@Flogger
1
private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
@JBossLog
1
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
1
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
1
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
1
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
1
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
1
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
----本文结束 感谢您的阅读----