覆盖equals()时总要覆盖hashCode()

覆写如下:

public class User
{
  private Integer id;
  private String userName;
  private String passWord;

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public String getUserName() {
    return userName;
  }

  public void setUserName(String userName) {
    this.userName = userName;
  }

  public String getPassWord() {
    return passWord;
  }

  public void setPassWord(String passWord) {
    this.passWord = passWord;
  }

  @Override
  public boolean equals(Object o)
  {
    if (this == o)
      return true;
    if (o == null || getClass() != o.getClass())
      return false;

    User user = (User) o;

    if (id != null ? !id.equals(user.id) : user.id != null)
      return false;
    if (userName != null ? !userName.equals(user.userName)
    : user.userName != null) {
      return false;
    }
    if (passWord != null ? !passWord.equals(user.passWord) : user.passWord != null) {
      return false;
    }

    return true;
  }

  @Override
  public int hashCode()
  {
    int result = id != null ? id.hashCode() : 0;
    result = 31 * result + (userName != null ? userName.hashCode() : 0);
    result = 31 * result + (passWord != null ? passWord.hashCode() : 0);
    return result;
  }
}

1、没有覆盖hashCode而违反的关键约定是第二条: 相等的对象必须具有相等的散列码。

2、重写hashcode选用31的原因:31是一个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为2相乘等价于移位运算,且31有个很好的特性,即用移位和减法来代替乘法,可以得到更好的性能:31*i= (i<<5)-i,现代的VM可以自动完成这种优化。

3. result = 31*result +c;

为每个关键域f计算int类型的散列码c规则如下:
1)boolean: 计算 (f?1:0);
2)byte,int,char,short: 计算 (int)f;
3) long: 计算(int)(f~(f>>>32));
4) float: 计算 Float.floatToIntBits(f);
5) double: 计算 Double.doubleToLongBits(f);
6) 对象引用或者数组:每个元素当做单独的域来处理

上一篇:关于JavaScript中实现继承,及prototype属性


下一篇:JavaScript中的继承(原型链)