HashSet中使用@Data注解問題
平時習慣使用lombok工具,免去了我們寫get
、set
方法之類的,當然了,我們使用@Data注解后,equals()
、hashCode()
、toString()
也省卻了。但是當你代碼存在繼承關系時,就得留心結果是否是你想要的了?
下面我直接列舉個例子吧:
父類:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Tag {
private Long id;
private String tagName;
private String position;
}
子類:
@Data
@NoArgsConstructor
public class UserTag extends Tag {
private Long userId;
public UserTag(Long id, String tagName, String position, Long userId) {
super(id, tagName, position);
this.userId = userId;
}
}
其實關系就這么easy,最后我們test來說明問題
public class UserTagTest {
public static void main(String[] args) {
UserTag firstUserTag = new UserTag(1L, "tag1", "up", 2000L);
UserTag secondUserTag = new UserTag(2L, "tag2", "down", 2000L);
Set<Tag> tagSet = <span class="hljs-keyword">new</span> HashSet<>();
<span class="hljs-keyword">boolean</span> firstAdd = tagSet.add(firstUserTag);
<span class="hljs-keyword">boolean</span> secondAdd = tagSet.add(secondUserTag);
System.out.println(<span class="hljs-string">"firstAdd:"</span> + firstAdd);
System.out.println(<span class="hljs-string">"secondAdd:"</span> + secondAdd);
System.out.println(<span class="hljs-string">"tagSet size:"</span> + tagSet.size());
}
}
運行實際結果:
firstAdd:true
secondAdd:false
tagSet size:1
當看着實際結果和預期結果不同,當然了,很容易就想到是equals()
和hashCode()
的問題。最后我反編譯看着@Data幫我們生成的equals()
和hashCode()
,如下:
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof UserTag)) {
return false;
} else {
UserTag other = (UserTag)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$userId = this.getUserId();
Object other$userId = other.getUserId();
if (this$userId == null) {
if (other$userId != null) {
return false;
}
} else if (!this$userId.equals(other$userId)) {
return false;
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof UserTag;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $userId = this.getUserId();
int result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
return result;
}
實際上只比較了userId
,說到這,得到上面的運行結果也就很正常了。
</div>