Object

每个c#或java程序员都非常熟悉object类。c++中没有根类。在java中,只有primitive type没有根类。

在观摩别人代码的过程中,我看到了大量类实现了equals和hashcode这样的方法而不明白为什么要这么做。这两个方法和object相关,因此今天学习这部分内容。

 

Equals方法

 

在object类中的equals用于检验两个对象是否相等。检验的方法就是看两个对象是否有同样的引用。

但是这样的操作没有什么实际意义。比如我们希望当两个雇员的姓名,工资和入职时间相等时,就认为这两个雇员是同一个人。尽管这两个对象的引用是不同的。

 

仔细看看判断了哪些东西:注意这个例子是一个equals方法的best practice

class Employee
{
. . .


@override //为了正确的调用这个方法,而不是不小心调用了object.equals,用这个参数强制覆盖父类的方法。

public boolean equals(Object otherObject)
{
// a quick test to see if the objects are identical, 这里的==实际调用的就是object的equals方法
if (this == otherObject ) return true;
// must return false if the explicit parameter is null
if (otherObject == null ) return false;
// if the classes don't match, they can't be equal
if (getClass() != otherObject.getClass() )
return false;
// now we know otherObject is a non-null Employee
Employee other = (Employee) otherObject;
// test whether the fields have identical values
return name.equals(other.name) && salary == other.salary && hireDay.equals(other.hireDay);
}
}

在子类manager中的equals方法中,先调用父类的equals方法做初步的判断:

 

class Manager extends Employee
{
. . .
public boolean equals(Object otherObject)
{
if (!super.equals(otherObject)) return false;

// super.equals checked that this and otherObject belong to the same class
Manager other = (Manager) otherObject;
return bonus == other.bonus;
}
}

 

在上面的例子中,如果两个对象不是同一个类,则认为不相等。但是这样产生了一个问题:一个manager m子类和一个employee e做比较的时候,会违反置换原则:

如果 x.equals(y) is true 那么 y.equals(x)也应该返回true。但明显manager和employee的例子违背了这个原则。

 

因此,我们需要根据实际需求而定。是认为m和e相等呢?还是不相等。可以选择使用getClass()或instanceOf()。

 

Hashcode方法

 

string类的hashcode是用下面算法产生的:

int hash = 0;
for (int i = 0; i < length(); i++)
hash = 31 * hash + charAt(i);

 

The hashCode method is defined in the Object class. Therefore, every object has a default
hash code
. That hash code is derived from the object’s memory address

 

如果重新定义了euqals方法,就必须重新定义hashcode方法,以便用户可以将对象插入到hash table中。(引用core java)

这里从网上search出了一些进一步的理由:


   “为啥很多地方说“覆写equals的时候一定要覆写hashCode”。说到这里我知道很多人知道有个原则:如果a.equals(b)那么要确保 a.hashCode()==b.hashCode()。为什么?hashCode和我写的程序的业务逻辑毫无关系,为啥我要override? 要我说如果你的class永远不可能放在hash code为基础的容器内,不必劳神,您真的不必override hashCode() :)

    说得准确一点放在HashMap和Hashtable里面如果是作为value而不是作为key的话也是不必override hashCode了。至于HashSet,实际上它只是忽略value的HashMap,每次HashSet.add(o)其实就是 HashMap.put(o, dummyObject)。

    那为什么放到Hash容器里面要overide hashCode呢?因为每次get的时候HashMap既要看equals是不是true也要看hash code是不是一致,put的时候也是要看equals和hash code。”

 

所以我会常常看到这个方法。

 

Your definitions of equals and hashCode must be compatible: if x.equals(y) is true, then
x.hashCode() must be the same value as y.hashCode(). For example, if you define
Employee.equals to compare employee IDs, then the hashCode method needs to hash
the IDs, not employee names or memory addresses.

看一个例子:上面的equals比较员工的姓名工资和入职时间,那么hashcode也要使用这些:

public int hashCode()
{

return 7 * name.hashCode()
+ 11 * new Double(salary).hashCode()
+ 13 * hireDay.hashCode();
}

 

最后再来看一段javadoc中的解释~~

hashCode

public int hashCode

()
Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable .

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer , but this implementation technique is not required by the JavaTM programming language.)

 

Returns:
a hash code value for this object.

//也就是说,object.hashcode()返回的是内存地址。所以如果重写了equals,同时要使用hashmap啥的,就很有override hashocde()的必要。否则equals认为相等的对象将会返回不用的hashcode。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值