开发者

Java equal and hashCode with non primitive types

开发者 https://www.devze.com 2023-01-09 00:55 出处:网络
I have a class with some non primitive members. class Relation { String name; Role roleFrom; Role roleTo;

I have a class with some non primitive members.

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

class Role {
  RoleType roleType;
  String details;
}
class Role开发者_JAVA技巧Type {
  String typeName;
  String details;
}

Two relations are equal, when

  1. the name are equal
  2. the role type (identified by unique typeName) are equal for the Role members (roleFrom and roleTo)

How to write equals and hashCode for class Relation. When tried with Netbeans, it only displays 3 fields (name, roleFrom and roleTo). Is it because, one should not access the primitive types in roleFrom and roleTo (roleType -> typeName). Or, please show an implementation.

thanks.


When implementing hashCode() and equals() with non-primitive types of fields, it is assumed that these types also implement hashCode() and equals() correctly. So go to the other classes and implement hashCode() and equals() there (again using the auto-generation features of your IDE).


You should be extremely careful when overriding your equals method, the best thing to do, as noted by Joshua Bloch in "Effective Java" is not to override it at all unless it is absolutely necessary, with the default equals implementation inherited from java.lang.Object every objects is only equals to itself.

I recommend that you check the following links to learn how to appropriately implement both your equals and hashCode methods. The last link shows you how to implement those methods when you have non primitive types as well as considerations for when you're dealing with inheritance.

  • http://java.sun.com/javase/6/docs/api/java/lang/Object.html#equals%28java.lang.Object%29
  • http://java.sun.com/javase/6/docs/api/java/lang/Object.html#hashCode%28%29
  • http://www.javaworld.com/javaworld/jw-06-2004/jw-0614-equals.html


One potential solution, assuming that you

  1. you must override equals for your implementations
  2. you want to be lazy
  3. you don't mind treating hashcode() and equals() methods as black boxes
  4. don't mind using an extra tool at compile time

is to try using Lombok's useful EqualsAndHashcode annotation to handle this for you. Granted, you should probably probably still read the links that @StudiousJoseph mentioned in his answer so you understand how to write proper equals/hashcode methods, but this a tool that can help relieve some of the pains and pitfalls of writing these methods yourself.

As others have mentioned, in your case, you'll need to at least use that annotation or override equals()/hashcode() on your Relations class and potentially on your Role and Roletype class too if you need custom equals behavior on them.

Edit: I just noticed you are using Netbeans. This may be relevant if you want to try Lombok: http://wiki.netbeans.org/Lombok#IDE_support


As others said, you need to implement equals/hashCode for the other two classes as well. Where's an example:

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);
  }
}

With regard to if(!(o instanceof XYZWK)) return false;: this is basically just fail-fast for the equals method, without generating (or needing a try/catch for) a ClassCastException.

0

精彩评论

暂无评论...
验证码 换一张
取 消