具有非原语类型的Java equal和hashCode

具有非原语类型的Java equal和hashCode,java,Java,我有一个包含一些非原始成员的类 class Relation { String name; Role roleFrom; Role roleTo; } class Role { RoleType roleType; String details; } class RoleType { String typeName; String details; } 两个关系是相等的,当 名字是相等的 角色成员(roleFrom和roleTo)的角色类型(由唯一的typeName标识

我有一个包含一些非原始成员的类

class Relation {
 String name;
 Role roleFrom;
 Role roleTo;
}

class Role {
  RoleType roleType;
  String details;
}
class RoleType {
  String typeName;
  String details;
}
两个关系是相等的,当

  • 名字是相等的
  • 角色成员(roleFrom和roleTo)的角色类型(由唯一的typeName标识)相等
  • 如何为类
    关系
    编写
    等于
    hashCode
    。当尝试使用Netbeans时,它只显示3个字段(
    name
    roleFrom
    roleTo
    )。是因为,不应该访问roleFrom和roleTo(roleType->typeName)中的基元类型。或者,请显示一个实现


    谢谢。

    当使用非原语类型的字段实现
    hashCode()
    equals()
    时,假定这些类型也正确实现了
    hashCode()
    equals()
    。因此,转到其他类并在那里实现
    hashCode()
    equals()
    (再次使用IDE的自动生成功能)。

    重写
    equals
    方法时应该非常小心,这是最好的做法,正如Joshua Bloch在《高效Java》中指出的那样除非绝对必要,否则根本不重写它,默认的equals实现继承自java.lang.Object,每个对象都只等于自身

    我建议您查看以下链接,了解如何适当地实现
    equals
    hashCode
    方法。最后一个链接向您展示了在具有非基本类型时如何实现这些方法,以及在处理继承时的注意事项


    正如其他人所说,您还需要为其他两个类实现
    equals
    /
    hashCode
    。举个例子:

    class Relation {
      String name;
      Role roleFrom;
      Role roleTo;
    
      public int hashCode() {
        // Just a sample. super.hashCode() would probably be better
        return name.hashCode() & roleFrom.hashCode() | roleTo.hashCode();
      }
    
      public boolean equals(Object o) {
        if(!(o instanceof Relation)) return false;
        Relation other = (Relation)o;
    
        return name.equals(other.name)
          && roleFrom.equals(other.roleFrom)
          && roleTo.equals(other.roleTo);
      }
    }
    
    class Role {
      RoleType roleType;
      String details;
    
      public int hashCode() {
        // Just a sample. super.hashCode() would probably be better
        return roleType.hashCode();
      }
    
      public boolean equals(Object o) {
        if(!(o instanceof Role)) return false;
        Role other = (Role)o;
    
        return roleType.equals(other.roleType);
      }
    }
    class RoleType {
      String typeName;
      String details;
    
      public int hashCode() {
        // Just a sample. super.hashCode() would probably be better
        return typeName.hashCode();
      }
    
      public boolean equals(Object o) {
        if(!(o instanceof RoleType)) return false;
        RoleType other = (RoleType)o;
    
        return typeName.equals(other.typeName);
      }
    }
    

    关于
    if(!(o instanceof XYZWK))返回false
    :对于
    equals
    方法,这基本上就是快速失败,而不需要为
    ClassCastException
    生成(或需要
    try
    /
    catch
    )一个潜在的解决方案,假设您

  • 您必须为您的实现重写equals
  • 你想偷懒吗
  • 您不介意将hashcode()和equals()方法视为黑盒
  • 不介意在编译时使用额外的工具
  • 就是尝试使用有用的工具来为您处理此问题。当然,您可能仍然应该阅读@StudiousJoseph在其回答中提到的链接,以便了解如何编写适当的equals/hashcode方法,但这是一个可以帮助您减轻自己编写这些方法的一些痛苦和陷阱的工具

    正如其他人所提到的,在您的例子中,如果您需要自定义equals行为,您至少需要在关系类上使用该注释或重写equals()/hashcode(),也可能在Role和Roletype类上使用


    编辑:我刚刚注意到您正在使用Netbeans。如果您想尝试Lombok:

    为什么super.hashCode()会更好,这可能与此相关?如果你重写equals,你需要重写hashCode。嗯,从技术上讲,你这里有个问题。您的RoleType.equals仅使用typeName,但RoleType.hashCode使用typeName和详细信息。因此,两个角色类型可以彼此相等,但具有不同的哈希代码,这违反了约定。@Jay:哎呀,当我意识到OP对
    equals
    的相等性仅取决于
    typeName
    @Steve Kuo:
    super时,我的意思是要删除它。
    super.hashCode()
    通常比自定义实现更好“只要合理可行,类
    Object
    定义的hashCode方法确实会为不同的对象返回不同的整数。”在这种情况下,
    super.hashCode()
    将为不同的对象返回不同的散列,而
    typeName.hashCode()
    只会为不同的
    typeName
    返回不同的散列。当涉及到诸如
    HashMap
    两个彼此相等的对象必须具有相同的哈希代码时,更独特的哈希代码更好。如果equals使用系统标识哈希代码以外的其他代码来表示相等,并且使用对象的hashCode(),则可能有两个equals对象使用不同的哈希代码。示例:两个彼此相等的不同对象将具有不同的系统标识哈希代码。+1表示“最好不要覆盖它,除非绝对必要”,感谢您的回复。。我是Java新手,所以我从来不知道它。在我的例子中,我可以执行列表操作,比如删除、包含、比较两个关系对象。您认为默认实现(我读为等于==(或相同的引用))足够了吗?我通过JPA(hibernate)检索我的对象。因此,如果我使用unique键查询它们(在本例中为name、roleFrom和roleTo),它将与检索到的关系(或在内存中)相同。所有这些对象都不是静态的或单例的。我正在看第一版(因为我没有第二版),但是布洛赫说“那么什么时候重写
    Object.equals
    ?当一个类具有不同于仅仅对象标识的逻辑相等概念,并且一个超类尚未重写
    equals
    来实现所需的行为时。“非常欢迎。如果您使用JPA,此链接可能会帮助您进一步了解如何安全地实现这些方法。并且:)