HashSet中使用@Data注解问题

平时习惯使用lombok工具,免去了我们写getset方法之类的,当然了,我们使用@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&lt;Tag&gt; tagSet = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
<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,说到这,得到上面的运行结果也就很正常了。

原文地址:https://www.jianshu.com/p/ec0bd0274942

      </div>

继承关系中子类使用@Data注解问题的更多相关文章

  1. C++反汇编第四讲,反汇编中识别继承关系,父类,子类,成员对象

    C++反汇编第四讲,反汇编中识别继承关系,父类,子类,成员对象 讲解目录: 1.各类在内存中的表现形式   备注: 主要复习开发知识,和反汇编没有关系,但是是理解反汇编的前提.     2.子类继承父 ...

  2. Java类继承关系中的初始化顺序

    Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类Ini ...

  3. JavaSE复习日记 : 继承关系和super关键字以及继承关系中方法的覆写

    /* * 类的继承和super关键字 * * 软件开发的三大目的: * 可拓展性; * 可维护性; * 可重用性; * * 这里单说下可重用性这一项: * 为了代码复用,复用方式有: * 函数的调用复 ...

  4. C#继承关系中【方发表】的创建和调用

    —C#继承关系中[方发表]的创建和调用 Insus.NET实现一个最炫最原创的验证码.你可以从下面的一步一步的演译. 实现一个验证码,需要了解的是,它最基本是随机产生字符串:<在ASP.NET ...

  5. 解惑《你必须知道的.net》——C#继承关系中【方发表】的创建和调用

    前言: 现在正在读<你必须知道的.net>(第二版)一书,看到IL语言那一章,将call.callvirt和calli时候,书中举了一个例子,是一个三层继承的例子,我一开始看的时候就有点懵 ...

  6. C++反汇编第三讲,反汇编中识别继承关系,父类,子类,成员对象

    讲解目录: 1.各类在内存中的表现形式   备注: 主要复习开发知识,和反汇编没有关系,但是是理解反汇编的前提.     2.子类继承父类 2.1 子类中有虚函数,父类中有虚函数 : 都有的情况下   ...

  7. java继承关系中成员变量,构造方法,成员方法的关系

    Java继承中的成员关系 A:成员变量 a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单写那个名字就访问那个名字! b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ...

  8. 1.7Oob 继承关系中构造方法的使用

    1:父类中最好要有一个空参数的构造方法,因为默认的构造方法在自定义了构造方法后就不存在了,需要显示的写出来. 若父类中没有空参数的构造方法,则子类必须有自定义的构造方法,且用super()调用父类的构 ...

  9. Java 中的多态,一次讲个够之继承关系中的多态

    多态是继封装.继承之后,面向对象的第三大特性. 现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态. Java作为面向对象的语言,同样可以描述一个 ...

随机推荐

  1. delphi 任务栏按钮闪烁(转)

    如果您创建的应用程序是运行在Windows 98或更高版本操作系统上,您可以通过调用API函数FlashWindowEx并赋给它一个FlashWInfo结构体来实现.  而如果是运行在Windows ...

  2. NX二次开发-UFUN获取面的内外边界UF_MODL_ask_loop_list_item

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <NXOpen/Face.hxx> #inclu ...

  3. SPSS如何调用已建立的数据文件

    SPSS如何调用已建立的数据文件 调用已建立的数据文件 SPSS可以调用SPSS(*.sav),Excel(*.xls),dBASE(*.dbf),ASCII(*.dat,*.txt)等数据文件. 2 ...

  4. AtCoder ABC 127E Cell Distance

    题目链接:https://atcoder.jp/contests/abc127/tasks/abc127_e 题目大意 给定一个$N*M$的棋盘,二元组$(x, y),1 \leq x \leq N, ...

  5. js实现下拉框

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. C++之关键字&标识符命名规则

    关键字 **作用:**关键字是C++中预先保留的单词(标识符) * **在定义变量或者常量时候,不要用关键字** C++关键字如下: 提示:在给变量或者常量起名称时候,不要用C++得关键字,否则会产生 ...

  7. Error resolving template,template might not exist or might not be accessible by any of the configured Template Resolvers

    template might not exist or might not be accessible by any of the configured Template Resolvers at o ...

  8. Docker学习の更改Docker的目录

    一.更改虚拟磁盘的目录 虚拟机的默认存储位置是C:\Users\Administrator\.docker\machine\machines ,后期docke镜像文件会不断增加,为了给系统盘减负,最好 ...

  9. Activiti学习笔记8 — UserTask私有任务的使用

    每一个UserTask都会在Execution表和Task表中各产生一条记录 一.创建流程引擎对象 /** * 1.创建流程引擎对象 */ private ProcessEngine processE ...

  10. Apache Spark 2.2.0 中文文档 - Spark RDD(Resilient Distributed Datasets)

    Spark RDD(Resilient Distributed Datasets)论文 概要 1: 介绍 2: Resilient Distributed Datasets(RDDs) 2.1 RDD ...