对于所有对象都通用的方法equals、hashCode
呵呵再补充下,摘录自我的wiki(读
- Effective Java中文版
笔记):
?
?
对于所有对象都通用的方法
?
- Object中的方法:equals,hashCode,toString,clone 和 finalize都有明确的通用约定,所以我们需要遵守,因为不少的类都是按照通用约定来工作的
?
覆盖equals时请遵守通用约定
?
- 覆盖equals方法有讲究的一下任意条件满足,都不应该覆盖equals
- 类的每个实例本质上都是唯一的,如:Thread不关心类是否提供了“逻辑相等”的测试功能:如java.util.Random.equals
超类已经覆盖了equals,并且子类认为是合适的,如:Map的equals实现继承了?AbstractMap.equals,List的equals实现继承了?AbstractList的equals
类是私有的或是包级私有的,可以确定永远不会被调用equals方法: 需要覆盖equals:throw new??AssertionError("不要调用我");
如果类有自有的“逻辑相等”就需要覆盖equals方法了equals通用约定:- 自反性:对于任何非空x,x.equals(x)==true对称性:对于任何非空x、y,x.equals(y)==y.equals(x);传递性:对于任何非空x、y、z,如果x.equals(y)==true、y.equals(z)==true那么x.equals(z)==true;
- java.sql.Timestamp和java.util.Date的问题:"鉴于 Timestamp 类和上述 java.util.Date 类之间的不同,建议代码一般不要将 Timestamp 值视为 java.util.Date 的实例。Timestamp 和 java.util.Date 之间的继承关系实际上指的是实现继承,而不是类型继承。"
- java.net.URL.equals的调用依赖于网络,每次调用它们的内在可能变化
- 使用==检查参数是否为这个对象的引用:if (o == this) return true;instance of进行类型检查把参数转化为正确的类型每个关键域检查它们是否匹配
- 非float和double的基本类型直接==比较float使用Float.compare比较double使用Double.compare比较对于对象引用直接调用equals比较如果是数组域,如果每个元素都是关键域,那么每一个都要比较,jdk1.5后可以通过Arrays.equals解决
- 覆盖equals时总要覆盖hashCode不要企图让equals过于智能不要讲equals中的参数替换为其他类型,这不是覆盖而是重载,所以需要@Override注解
?
覆盖equals时总要覆盖hashCode
?
- hashCode 的常规协定是:
- 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
- 把非0的常数值保存到result中,如17对于每一个关键域f(equals中涉及的每个域),完成以下步骤:
- 为该域计算int型散列码c:
- boolean return f?1:0byte、char、sort或int return f;
long return (int)(f^(f>>>32))
float return Float.floatToIntBits(f)double return Double.doubleToLongBits(f)再作为long型来计算散列值引用对象return null?0:f.hasCode();如果是数组,递归处理每一个元素