Lombok
1、簡單概述
工作中大量重復毫無技術的去書寫get()、set()方法,不推薦手寫,也不推薦利用idea中的工具類等等操作
而是使用lombok中的注解來一套搞定。
既然lombok能夠搞定,那么需要理解一下是如何來搞定這一切的。
lombok除了get/set,還有一些其他的可以使用的。
可以去看一下官網:
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
lombok是一款比較常用的工具,可以用來幫助開發人員消除java中的冗長代碼(也就是毫無技術可言的重復性工作),尤其是對於簡單的java對象(POJO),通過注解實現這一目的。
Lombok可以簡化我們的代碼書寫方式。
Lombok的原理:
JSR269:插件化注解處理API
JDK6提供的特性,在javac編譯期間利用注解搞事情。在編譯期間可以利用lombok的注解方式來進行將生成的代碼添加到字節碼文件中去。我們利用Lombok注解生成的字節碼文件中是包含了的。
二、使用
最常用的注解
2.1、@Data
可以自動的幫助我們生成get/seter、toString、hashcode和equals方法,但是呢,我們可以看到這種使用方式:
@Data
public class User {
private String name;
}
在idea中看到對應的class目錄:
public class User {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
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 {
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(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
}
可以看到其中的方法已經在上面對應好了,而且生成的還是當前類中的屬性。
但是問題就出現在這里,我再寫一個父類:
@Data
public class Person {
private Integer id;
}
然后讓其子類來進行繼承:
@Data
@EqualsAndHashCode(callSuper = true)
public class User extends Person{
private String name;
}
編譯后的Java如下所示:
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
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 if (!super.equals(o)) {
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(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = super.hashCode();
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
可以看到在equals方法中多了一個判斷
if (!super.equals(o))
return false;
@EqualsAndHashCode(callSuper = true)的作用就在於將子類和父類中的屬性都來進行比較,舉個例子進行說明:
父類Person:
@Data
public class Person {
private Integer id;
}
子類User:
@Data
public class User extends Person{
private String name;
}
測試方法:
@Test
void contextLoads() {
User user1 = new User();
User user2= new User();
user1.setId(1);
user2.setId(2);
user1.setName("1");
user2.setName("1");
boolean equals = Objects.equals(user1, user2);
log.info("兩個對象是否是相等的?------>{}",equals); //true
}
但是如果加了@EqualsAndHashCode(callSuper = true)
父類:
@Data
public class Person {
private Integer id;
}
子類:
@Data
@EqualsAndHashCode(callSuper = true)
public class User extends Person{
private String name;
}
再次運行測試類得到的卻是false,那么為什么會有這樣子的結果?
我們可以在不加@EqualsAndHashCode(callSuper = true)和不加的情況下分別看下class文件
2.2、@EqualsAndHashCode
不加@EqualsAndHashCode(callSuper = true)
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
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 {
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(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
}
加了@EqualsAndHashCode(callSuper = true)
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
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 if (!super.equals(o)) {
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(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = super.hashCode();
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
綜合這兩個情況來進行對比,可以看到加了@EqualsAndHashCode(callSuper = true)之后,生成的equals方法中多了一個判斷:
if (!super.equals(o)) {
return false;
}
這里是在訪問父類中的equals方法來進行判斷,但是有時候我們希望使用到父類中的屬性,有時候希望使用到子類中的屬性。
所以我們需要根據當前的場景來進行選擇,我現在使用的是直接將@EqualsAndHashCode(callSuper = false)
public class User extends Person {
private String name;
public User() {
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User(name=" + this.getName() + ")";
}
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 {
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(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $name = this.getName();
int result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
}
可以看到這里和不加@EqualsAndHashCode是一樣的,但是為了有些場景我們又需要不加上,所以需要根據自己的場景來進行判斷
2.3、@Accessors
@Accessors(chain=true)
鏈式訪問,該注解設置chain=true
,生成setter方法返回this,代替了默認的返回void。
@Data
@Accessors(chain=true)
public class User {
private Integer id;
private String name;
private Integer age;
public static void main(String[] args) {
User user=new User().setAge(31).setName("pollyduan");
System.out.println(user);
}
}
@Accessors(fluent = true)
與chain=true
類似,區別在於getter和setter不帶set和get前綴。但是這個盡量不要使用,因為很多框架都是通過get/set方法來進行賦值的
@Data
@Accessors(fluent=true)
public class User {
private Integer id;
private String name;
private Integer age;
public static void main(String[] args) {
User user=new User().age(31).name("pollyduan");
System.out.println(user);
}
}
@Accessors(prefix = “f”)
去除掉屬性的前綴之后生成的set方法:
@Data
@Accessors(prefix = "f")
public class User {
private String fName = "Hello, World!";
public static void main(String[] args) {
User user=new User();
user.setName("pollyduan");//注意方法名
System.out.println(user);
}
}
2.4、@NoArgsConstructor
無參構造
public User() {
}
2.5、@AllArgsConstructor
當前類中的屬性的有參構造:
public User(String name) {
this.name = name;
}
2.6、@Builder
這個方法可以用也可以不用,我這里不用,做個記錄。