java~lombok的@Data引發的問題(ti)
我們問題lombok是可以精簡我們的代碼的,讓開發人員把精力放在業務上,而它封裝的注解我們在使用時,需要多注意一下;@Data注解它是一個混合注釋,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode的(de)(de)功能,而我(wo)們問題@EqualsAndHashCode是(shi)(shi)重寫equals和hash的(de)(de)注(zhu)釋(shi),如(ru)果你是(shi)(shi)一個類,那可(ke)以不關心它(ta);而如(ru)果你的(de)(de)類中有(you)繼承(父類子類),那么(me)就要注(zhu)意一下了。
危險的@Data
子類不能完全代表父類
@EqualsAndHashCode注解里有個字段callSuper,它的默認值是false,意思是在重寫時,不會將父類的字段寫到equals里;而@Data這個注解由于包含了@EqualsAndHashCode,所以它也有這個特性,即子類強制實現了重寫equals和hashCode,并且只重寫了自己的屬性,這時,問題就來了,當兩個對象比較時,如果子類屬性相同而父類屬性不同,結果也為true,這是非常嚴重的bug。
定(ding)義(yi)兩(liang)種(zhong)類,基類People,和兩(liang)個子類Man和Woman
@Data
class Person {
String name;
}
@Data
//重寫時帶上父類字段
@EqualsAndHashCode(callSuper = true)
class Man extends Person {
Boolean hunting;
}
@Data
//重寫equals時不會帶上父類的字段,同種類型比較時,當子類字段相同時,結果就為true,這顯然是不準確的.
@EqualsAndHashCode(callSuper = false)
class Woman extends Person {
Boolean spin;
}
測試的結果,我們是可以猜出來的,父類里的字段不相同時,結果應該為false,但如果 @EqualsAndHashCode(callSuper = false),結果竟然是true,這也是正常的,因為(wei)它并沒有重(zhong)寫(xie)父類的屬性(xing)name,所(suo)以只要子類字段相同,結果就(jiu)認為(wei)相同了。
@Test
public void supperSubEqual() {
Man man = new Man();
man.setName("zzl");
man.setHunting(true);
Man man1 = new Man();
man1.setHunting(true);
man1.setName("lind");
log.info("man==man1 ? {}", man.equals(man1)); // false
Woman woman = new Woman();
woman.setName("zzl");
woman.setSpin(true);
Woman woman1 = new Woman();
woman1.setSpin(true);
woman1.setName("lind");
log.info("woman==woman1 ? {}", woman.equals(woman1)); // true
}

總結
在使用@Data時,我(wo)們盡(jin)量(liang)把(ba) @EqualsAndHashCode(callSuper = true)加(jia)上,因為你不加(jia),它相(xiang)當于是(shi)false;或者杜絕使用@Data,而用@Getter,@Setter,@ToString代替(ti)它。