@Data注解使用時的注意事項


在項目開發時,有實體類繼承了基類,切面中想用基類的字段往數據庫寫,但是發現基類的get set沒有被@Data創建出來。上網查了一下,看到一篇關於父子類的屬性沖突的記錄一下。

原文鏈接:https://blog.csdn.net/huluwa10526/article/details/108845383

 

※.首先想創建出父類的get set,要在父類上也加@Data,父類不加data注解,在用子實例類調用時是調不到父類屬性的。

 

@Data取代Get,Set方法的使用總結以及注意事項
前言:
開發過程中發現前輩的代碼中實體類沒有任何get,set方法但是卻能正常使用get,set方法,仔細研究發現每個實體類中都使用了@Data 注解於是仔細研究了下@Data的使用方法。

介紹:
@Data 注解的主要作用是提高代碼的簡潔,使用這個注解可以省去代碼中大量的get()、 set()、 toString()等方法;

使用:
要使用 @Data 注解要先引入lombok工具類庫,可以用簡單的注解形式來簡化代碼,提高開發效率。

在maven中添加依賴

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>

注意!
在編譯器中添加插件
這里以IDEA為例,在setting的plugin里搜索lombok plugin,安裝插件。重啟即可。

接下來就是寫實體類的時候就可以直接使用這個標簽了!
例如:

@Data
public class UsersDto {
@Id
private Integer id;
private String name;
private String password;
/**
* 性別 0男生 1女生
*/
private Byte sex;
private String email;
private String city;
}

常用的幾個注解:
@Data : 注在類上,提供類的get、set、equals、hashCode、canEqual、toString方法
@AllArgsConstructor : 注在類上,提供類的全參構造
@NoArgsConstructor : 注在類上,提供類的無參構造
@Setter : 注在屬性上,提供 set 方法
@Getter : 注在屬性上,提供 get 方法
@EqualsAndHashCode : 注在類上,提供對應的 equals 和 hashCode 方法
@Log4j/@Slf4j : 注在類上,提供對應的 Logger 對象,變量名為 log

這樣使用是不是很方便?
但是!
多年的經驗告訴我,有失就有得,為什么這么好用的標簽沒有大面積使用呢?於是乎我深入研究了一下這個標簽的使用,發現原來@Data標簽還有這么多的注意事項,如果沒注意的話,項目很可能出現難以預料的bug而且排查起來也很困難,下面舉例說明,也順便警醒自己和看到這篇文章的大家,如果遇到新的工具,沒研究透之前,千萬別貿然使用到項目中。

@Data注解它是一個混合注釋,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode的功能,而我們問題@EqualsAndHashCode是重寫equals和hash的注釋,如果你是一個類,那可以不關心它;而如果你的類中有繼承(父類子類),那么就要注意一下了

package com.*.user;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Objects;
//@RunWith(SpringRunner.class)
//@SpringBootTest
public class LombokTest {
@Data
class Person {
String name;
int age;
}
@Data
//重寫時帶上父類字段
@EqualsAndHashCode(callSuper = true)
class Man extends Person {
Boolean hunting;
}
@Data
//重寫equals時不會帶上父類的字段,同種類型比較時,當子類字段相同時,結果就為true,這顯然是不准確的.
@EqualsAndHashCode(callSuper = false)
class Woman extends Person {
Boolean spin;
}
@Test
public void tsetlombok() {
Man t1 = new Man();
Man t2 = new Man();
t1.setName("123");
t2.setName("12345");
String name = "1";
t1.name = name;
t2.name = name;
int age = 1;
t1.age = age;
t2.age = age;

System.out.println(t1.equals(t2));//true
System.out.println(t2.equals(t1));//true
System.out.println(t1.hashCode());//376050
System.out.println(t2.hashCode());//376050
System.out.println(t1 == t2);//false
System.out.println(Objects.equals(t1, t2));//true
}

@Test
public void supperSubEqual() {
Man man = new Man();
man.setName("小張");
man.setAge(22);
man.setHunting(true);
Man man1 = new Man();
man1.setHunting(true);
man1.setName("小李");
man.setAge(23);
System.out.println("man==man1?"+ man.equals(man1)); // false

Woman woman = new Woman();
woman.setName("小趙");
man.setAge(19);
woman.setSpin(true);
Woman woman1 = new Woman();
woman1.setSpin(true);
man.setAge(18);
woman1.setName("小美");
System.out.println("woman==woman1? "+ woman.equals(woman1)); // true
}
}

@EqualsAndHashCode注解里有個字段callSuper,它的默認值是false,意思是在重寫時,不會將父類的字段寫到equals里;而@Data這個注解由於包含了@EqualsAndHashCode,所以它也有這個特性,即子類強制實現了重寫equals和hashCode,並且只重寫了自己的屬性,這時,問題就來了,當兩個對象比較時,如果子類屬性相同而父類屬性不同,結果也為true,這是非常嚴重的bug。

通過以上兩個test我們發現:
父類里的字段不相同時,結果應該為false,但如果 @EqualsAndHashCode(callSuper = false),結果竟然是true,這是因為它並沒有重寫父類的屬性name,所以只要子類字段相同,結果就認為相同了。

所以在使用@Data時,我們盡量把 @EqualsAndHashCode(callSuper = true)加上,因為你不加,它相當於是false;

優點:
1、能通過注解的形式自動生成構造器、getter/setter、equals、hashcode、toString等方法,提高了一定的開發效率
2、讓代碼變得簡潔,不用過多的去關注相應的方法
3、屬性做修改時,也簡化了維護為這些屬性所生成的getter/setter方法等

缺點:
1、不支持多種參數構造器的重載
2、雖然省去了手動創建getter/setter方法的麻煩,但大大降低了源代碼的可讀性和完整性

總結:
1、用了@Data就不要有繼承關系
2、自己重寫equals(), Lombok 不會對顯式重寫的方法進行生成。
3、顯式使用@EqualsAndHashCode(callSuper = true), Lombok 會以顯式指定的為准。
4、或者杜絕使用@Data,而用@Getter,@Setter,@ToString代替它。

lombok 只是省去了一些人工生成代碼的麻煩,但是這些getter/setter等等的方法,用IDE的快捷鍵也可很方便的生成。況且,有時通過給getter/setter加一點點業務代碼(但通常不建議這么加),能極大的簡化某些業務場景的代碼。
用還是不用,這中間如何取舍,自然是要看項目的需要,靈活運用。

原文鏈接:https://blog.csdn.net/huluwa10526/article/details/108845383


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM