wang9354
Java中equals()和hashCode() 的重写
以下内容总结自《Effective Java》。
1.何时需要重写equals()
当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念)。
2.设计equals()
[1]使用instanceof操作符检查“实参是否为正确的类型”。
[2]对于类中的每一个“关键域”,检查实参中的域与当前对象中对应的域值。
[2.1]对于非float和double类型的原语类型域,使用==比较;
[2.2]对于对象引用域,递归调用equals方法;
[2.3]对于float域,使用Float.floatToIntBits(afloat)转换为int,再使用==比较;
[2.4]对于double域,使用Double.doubleToLongBits(adouble) 转换为int,再使用==比较;
[2.5]对于数组域,调用Arrays.equals方法。
3.当改写equals()的时候,总是要改写hashCode()
根据一个类的equals方法(改写后),两个截然不同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode方法,它们仅仅是两个对象。因此,违反了“相等的对象必须具有相等的散列码”。
4.设计hashCode()
[1]把某个非零常数值,例如17,保存在int变量result中;
[2]对于对象中每一个关键域f(指equals方法中考虑的每一个域):
[2.1]boolean型,计算(f ? 0 : 1);
[2.2]byte,char,short型,计算(int);
[2.3]long型,计算(int) (f ^ (f>>>32));
[2.4]float型,计算Float.floatToIntBits(afloat);
[2.5]double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行[2.3];
[2.6]对象引用,递归调用它的hashCode方法;
[2.7]数组域,对其中每个元素调用它的hashCode方法。
[3]将上面计算得到的散列码保存到int变量c,然后执行 result=37*result+c;
[4]返回result。
5.示例
下面的这个类遵循上面的设计原则,重写了类的equals()和hashCode()。
package
com.zj.unit;
import
java.util.Arrays;
/** */
/**
wangdei
http://www.bt285.cn
*
*/
public
class
Unit
{
private
short
ashort;
private
char
achar;
private
byte
abyte;
private
boolean
abool;
private
long
along;
private
float
afloat;
private
double
adouble;
private
Unit aObject;
private
int
[] ints;
private
Unit[] units;
public
boolean
equals(Object o)
{
if
(
!
(o
instanceof
Unit))
return
false
;
Unit unit
=
(Unit) o;
return
unit.ashort
==
ashort
&&
unit.achar
==
achar
&&
unit.abyte
==
abyte
&&
unit.abool
==
abool
&&
unit.along
==
along
&&
Float.floatToIntBits(unit.afloat)
==
Float
.floatToIntBits(afloat)
&&
Double.doubleToLongBits(unit.adouble)
==
Double
.doubleToLongBits(adouble)
&&
unit.aObject.equals(aObject)
&&
equalsInts(unit.ints)
&&
equalsUnits(unit.units);
}
private
boolean
equalsInts(
int
[] aints)
{
return
Arrays.equals(ints, aints);
}
private
boolean
equalsUnits(Unit[] aUnits)
{
return
Arrays.equals(units, aUnits);
}
public
int
hashCode()
{
int
result
=
17
;
result
=
37
*
result
+
(
int
) ashort;
result
=
37
*
result
+
(
int
) achar;
result
=
37
*
result
+
(
int
) abyte;
result
=
37
*
result
+
(abool
?
0
:
1
);
result
=
37
*
result
+
(
int
) (along
^
(along
>>>
32
));
result
=
37
*
result
+
Float.floatToIntBits(afloat);
long
tolong
=
Double.doubleToLongBits(adouble);
result
=
37
*
result
+
(
int
) (tolong
^
(tolong
>>>
32
));
result
=
37
*
result
+
aObject.hashCode();
result
=
37
*
result
+
intsHashCode(ints);
result
=
37
*
result
+
unitsHashCode(units);
return
result;
}
private
int
intsHashCode(
int
[] aints)
{
int
result
=
17
;
for
(
int
i
=
0
; i
<
aints.length; i
++
)
result
=
37
*
result
+
aints[i];
return
result;
}
private
int
unitsHashCode(Unit[] aUnits)
{
int
result
=
17
;
for
(
int
i
=
0
; i
<
aUnits.length; i
++
)
result
=
37
*
result
+
aUnits[i].hashCode();
return
result;
}
}
posted on 2009-02-25 20:26
wang9354
阅读(1538)
评论(0)
编辑
收藏
导航
BlogJava
首页
新随笔
联系
聚合
管理
<
2009年2月
>
日
一
二
三
四
五
六
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
统计
随笔 - 12
文章 - 0
评论 - 0
引用 - 0
常用链接
我的随笔
我的评论
我的参与
留言簿
(2)
给我留言
查看公开留言
查看私人留言
随笔档案
2009年4月 (1)
2009年3月 (7)
2009年2月 (4)
友情链接
搬家公司
讨债公司
搜索
最新评论
阅读排行榜
1. 一位软件工程师的7年总结(4502)
2. 解决tomcat经常挂掉的问题(3414)
3. 调用java API发送传真(2402)
4. Nexus图文介绍(2352)
5. 用java的Robot类来实现屏幕抓图(2234)
评论排行榜
1. 一位软件工程师的7年总结(0)
2. 编写Action测试web用例(0)
3. 解决tomcat经常挂掉的问题(0)
4. Nexus图文介绍(0)
5. 借用Java1.5中面向(AOP)编程(0)