到目前为止,还能保持每天抽出一小时来学习。不过由于时间紧,所以一直没来得及进行学习记录,趁着现在有点时间,赶紧补一补
第8条:在改写equals的时候请遵守通用约定
改写equals方法看似简单,但是有许多的改写方式会导致错误,避免问题最容易的方式就是不改写。那么我们什么时候equals呢?当一个类有自己特有的“ 逻辑相等”概念(不同于对象身份的概念),而且超类也没有改写e q u a l s以实现期望的行为,这时我们需要改写e q u a l s方法。这通常适合于“ 值类(value class )”的情形,比如I n t e g e r或者date。程序员在利用e q u a l s方法来比较两个指向值对象的引用的时候,希望知道它们逻辑上是否相等,而不是它们是否指向同一个对象。为了满足程序员的要求,改写e q u a l s方法是必需的,而且这样做也使得这个类的实例可以被用做映射表( m a p)的键( k e y),或者集合(s e t)的元素,并使映射表或者集合表现出预期的行为。
改写equals的时候必须遵守它的通用约定:
e q u a l s方法实现了等价关系( equivalence re l a t i o n):
自反性 (reflexive)。对于任意的引用值x,x.equals(x)一定为true。
对称性 (symmetric).对于任意的引用值x和y,当且仅当y.equals(x)返回true是,x.equals(y)也一定返回true。
传递性 (transitive)。对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回true。
一致性 (consistent)。对于任意的引用值x和y,如果用于equals比较的对象信息没有被修改的话,那么,多次地哦啊用x.equals(y)要么一致的返回true,要么一致的返回false。
非空性 (nun-nullity)。对于任意的非空引用值x,x.equals(null)一定返回false。
第9条:改写equals时总是要改写hashCode
一个很常见的错误根源在于没有改写hashCode方法。在每个改写了equals方法的类中,你必须也要改写hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法与所有基于散列值( hash)的集合类结合在一起正常运作,这样的集合类包括HashMap、HashSet和Hashtable。
下面是hashCode约定的内容,来自java.lang.Object的规范:
• 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,那么,对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,这个整数可以不同,即这个应用程序这次执行返回的整数与下一次执行返回的整数可以不一致。
• 如果两个对象根据equals (Object)方法是相等的,那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果。
• 如果两个对象根据equals(Object)方法是不相等的,那么调用这两个对象中任一个对象的hashCode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列表(hash table)的性能。
第10条:始终要覆盖toString
java.lang.Object提供了一个toString方法的实现。它包含类的名称,以及一个“@”符号,接着是散列码的无符号十六进制,如“PhoneNumber@163b91”。这个结果通常不是我们想要的,所以toString的通用约定指出“建议所有的子类都覆盖这个方法”。
提供好的toString方法,不仅仅有利于这个类的实例,同样也利于那些包含这些实例的引用的对象,特别是集合对象。