Lombok入门
通过使用Lombok来略去编写私有成员变量的get和set方法。减少了大量的代码冗余。、
使用Maven导入
1 2 3 4 5 6
| <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <scope>compile</scope> </dependency>
|
原理解析
Lombok是一种插件化注解API,是通过添加注解来实现的,然后在javac进行编译的时候,进行处理。
源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Data public class User { public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
private Integer id;
private String username;
private String password; }
|
编译后的由字节码反编译的代码:
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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| public class User { private Integer id; private String username; private String password;
public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public Integer getId() { return this.id; }
public String getUsername() { return this.username; }
public String getPassword() { return this.password; }
public void setId(Integer id) { this.id = id; }
public void setUsername(String username) { this.username = username; }
public void setPassword(String password) { this.password = password; }
public boolean equals(Object o) { if (o == this) { return true; } else if (!(o instanceof User)) { return false; } else { User other = (User)o; if (!other.canEqual(this)) { return false; } else { label47: { Object this$id = this.getId(); Object other$id = other.getId(); if (this$id == null) { if (other$id == null) { break label47; } } else if (this$id.equals(other$id)) { break label47; }
return false; }
Object this$username = this.getUsername(); Object other$username = other.getUsername(); if (this$username == null) { if (other$username != null) { return false; } } else if (!this$username.equals(other$username)) { return false; }
Object this$password = this.getPassword(); Object other$password = other.getPassword(); if (this$password == null) { if (other$password != null) { return false; } } else if (!this$password.equals(other$password)) { return false; }
return true; } } }
protected boolean canEqual(Object other) { return other instanceof User; }
public int hashCode() { int PRIME = true; int result = 1; Object $id = this.getId(); int result = result * 59 + ($id == null ? 43 : $id.hashCode()); Object $username = this.getUsername(); result = result * 59 + ($username == null ? 43 : $username.hashCode()); Object $password = this.getPassword(); result = result * 59 + ($password == null ? 43 : $password.hashCode()); return result; }
public String toString() { Integer var10000 = this.getId(); return "User(id=" + var10000 + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ")"; } }
|
我们可以看到,Lombok在编译的时候帮助我们添加了很多有用的方法,如get,set,equals,tostring等。
具体标签
可以将这两个标签添加在类前,表示给这个类的所有非静态成员变量添加(set / get)方法。
同时,声明为final的成员变量,Lombok不会为它生成Setter方法。
源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Setter public class User { public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
private Integer id;
private String username;
private String password; }
|
编译后的由字节码反编译的代码:
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 User { private Integer id; private String username; private String password;
public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public void setId(Integer id) { this.id = id; }
public void setUsername(String username) { this.username = username; }
public void setPassword(String password) { this.password = password; } }
|
同时可以在标签后添加权限控制,例如:
源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Setter(AccessLevel.PUBLIC) @Getter(AccessLevel.PROTECTED) public class User { public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
private Integer id;
private String username;
private String password; }
|
编译后的由字节码反编译的代码:
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
| public class User { private Integer id; private String username; private String password;
public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public void setId(Integer id) { this.id = id; }
public void setUsername(String username) { this.username = username; }
public void setPassword(String password) { this.password = password; }
protected Integer getId() { return this.id; }
protected String getUsername() { return this.username; }
protected String getPassword() { return this.password; } }
|
可以看到,经过我们的设置,所有的get方法的访问权限都为protected,所有的set方法的访问权限都为public。
同时,该标签还可以添加在成员变量之前:
源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class User { public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; } @Getter private Integer id;
@Getter @Setter private String username;
@Getter private String password; }
|
编译后的由字节码反编译的代码:
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
| public class User { private Integer id; private String username; private String password;
public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public Integer getId() { return this.id; }
public String getUsername() { return this.username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return this.password; } }
|
如果在静态成员变量前添加标签,生成的getter和setter方法都将是静态的。
@Accessors
通过Accessors标签来设置@Getter和@Setter的样式。
@Accessors(chain = true)
该类的Setter方法会返回this(即该类的实例),所以我们就可以链式调用这些方法,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public User setId(Integer id) { this.id = id; return this; }
public User setUsername(String username) { this.username = username; return this; }
public User setPassword(String password) { this.password = password; return this; }
|
在使用时,可以这样:
1 2 3 4
| public void Usertry() { User user = new User(); user.setUsername("abaaba").setPassword("123").setId(1); }
|
@Accessors(fluent = true)
会通过多态,直接将Setter和Getter的方法名全设置为成员变量的名字。
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Accessors(fluent = true) @Getter @Setter public class User { public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public User() {};
private Integer id;
private String username;
private String password; }
|
编译后的由字节码反编译的代码:
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
| public class User { private Integer id; private String username; private String password;
public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public User() { }
public Integer id() { return this.id; }
public String username() { return this.username; }
public String password() { return this.password; }
public User id(Integer id) { this.id = id; return this; }
public User username(String username) { this.username = username; return this; }
public User password(String password) { this.password = password; return this; } }
|
为该类实现一个toString方法。
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @ToString public class User { public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public User() {};
private Integer id;
private String username;
private String password; }
|
编译后的由字节码反编译的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class User { private Integer id; private String username; private String password;
public User(int id, String username, String password) { this.id = id; this.password = password; this.username = username; }
public User() { }
public String toString() { return "User(id=" + this.id + ", username=" + this.username + ", password=" + this.password + ")"; } }
|
还可以通过添加不同参数来限制toString的功能。
includeFieldNames
1 2
| @ToString(includeFieldNames = false) public class User {
|
1 2 3
| public String toString() { return "User(" + this.id + ", " + this.username + ", " + this.password + ")"; }
|
默认为True,False状态下tostring隐藏成员变量的类型。
exclude
1 2
| @ToString(exclude = {"id"}) public class User {
|
1 2 3
| public String toString() { return "User(username=" + this.username + ", password=" + this.password + ")"; }
|
在exclude中添加想要省略的成员变量的名称(字符串),toString函数会省略这些成员变量的转化。
of
1 2
| @ToString(of = {"id"}) public class User {
|
1 2 3
| public String toString() { return "User(id=" + this.id + ")"; }
|
在of中添加想要显示的成员变量的名称(字符串),toString函数只会完成这些成员变量的转化。(与exclude相反)
callSuper
1 2
| @ToString(callSuper = true) public class User {
|
1 2 3 4
| public String toString() { String var10000 = super.toString(); return "User(super=" + var10000 + ", id=" + this.id + ", username=" + this.username + ", password=" + this.password + ")"; }
|
默认为false,改为true后会调用父类的toString()方法。
doNotUseGetters
如果成员变量存在getter方法,在tostring时会默认调用getter方法来获取成员变量。将该值设为true后将直接获取成员变量的值。
onlyExplicitlyIncluded
1 2
| @ToString(onlyExplicitlyIncluded = true) public class User {
|
默认为false,设为true后将只会显示类名
1 2 3
| public String toString() { return "User()"; }
|
Include
rank
通过添加rank来规定转化后字符串中变量的顺序。(rank值越大优先级越高)
1 2 3 4 5 6 7 8
| @ToString.Include(rank = 1) private Integer id;
@ToString.Include(rank = 0) private String username;
@ToString.Include(rank = 2) private String password;
|
1 2 3
| public String toString() { return "User(password=" + this.password + ", id=" + this.id + ", username=" + this.username + ")"; }
|
name
设置别名,添加后转化后的字符串中变量的类型将会被别名替换掉
1 2
| @ToString.Include(name = "学号") private Integer id;
|
1 2 3
| public String toString() { return "User(password=" + this.password + ", 学号=" + this.id + ", username=" + this.username + ")"; }
|
该标签只允许添加在类前。
重写Equals方法,使得类在比较的过程中对成员变量进行一一的确认,以此来比较是否相等。
该标签也包括exclude和of方法,具体功能和@TosString类似。
1 2
| @AllArgsConstructor public class User {
|
1 2 3 4 5
| public User(Integer id, String username, String password) { this.id = id; this.username = username; this.password = password; }
|
该标签只能添加在类前,默认为类生成全参数构造。
注意:添加该标签后会使得默认的无参构造方法失效。
该标签也可添加access注解来限制构造方法的访问控制。
1 2
| @AllArgsConstructor(access = AccessLevel.PUBLIC) public class User {
|
该标签也可添加staticName注解来添加public的静态 类构造方法 ,添加后,原来的无参构造方法的可访问性将被修改成private
1 2
| @AllArgsConstructor(staticName = "setUser") public class User {
|
1 2 3 4 5 6 7 8 9
| private User(Integer id, String username, String password) { this.id = id; this.username = username; this.password = password; }
public static User setUser(Integer id, String username, String password) { return new User(id, username, password); }
|
可以看到,自动生成了一个名为“setUser”的静态全参构造方法。
@NoArgsConstructor
生成默认的无参构造方法。
1
| @NoArgsConstructor(access = AccessLevel.PUBLIC)
|
其余参数和@AllArgsConstructor一致。
为类中生成包含对标记为final或者@NonNull的成员变量的赋值的构造方法。
1 2 3 4 5 6
| @RequiredArgsConstructor public class User { @NonNull private Integer id; final private String username;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class User { @NonNull private Integer id; private final String username; private String password;
public User(@NonNull Integer id, String username) { if (id == null) { throw new NullPointerException("id is marked non-null but is null"); } else { this.id = id; this.username = username; } } }
|
其余参数和@AllArgsConstructor一致。
该标签只能添加在类前。
等价于在类前同时添加了@Setter、@Getter、@RequiredArgsConstructor、@ToString、@EqualsAndHashCode。
添加@Data标签后不推荐对该类进行继承,可能会导致Equals方法异常。
@Value
具体功能和@Data类似。
但是!生成的所有成员变量的属性都是private final的(这意味着没有setter方法)。
@SneakyThrows
该标签只能添加在方法前,表示为该方法添加了try / catch。
1 2
| @SneakyThrows(IOException.class) public void abaaba() {
|
可以在注解之后添加异常的类来规定抛出的具体异常。
@Cleanup
为该变量自动添加close()方法。
@Builder
1 2
| @Builder public class User {
|
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
| public class User { private Integer id; private String username; private String password;
User(Integer id, String username, String password) { this.id = id; this.username = username; this.password = password; }
public static User.UserBuilder builder() { return new User.UserBuilder(); }
public static class UserBuilder { private Integer id; private String username; private String password;
UserBuilder() { }
public User.UserBuilder id(Integer id) { this.id = id; return this; }
public User.UserBuilder username(String username) { this.username = username; return this; }
public User.UserBuilder password(String password) { this.password = password; return this; }
public User build() { return new User(this.id, this.username, this.password); }
public String toString() { return "User.UserBuilder(id=" + this.id + ", username=" + this.username + ", password=" + this.password + ")"; } } }
|