本来应该是写第7条的,但是
发现我对第7条讲的东西不是很
理解,所以就暂时先跳过,以后可能会遇到这样的章节也会跳过,写
错误导别人罪过就大了。
覆盖equal方法看起来似乎很简单,但有很多覆盖方式会导致错误并导致很严重的后果。避免这类问题最简单的方法当然就是不覆盖equal方法。那么,我们要知道在哪些情况下就不需要覆盖equal方法呢?
只要满足下面任何一条,就可以,
1、类的每个实例本质上都是唯一的。对于代表活动实体而不是值的类,比如:Thread.
2、不关心类是否提供了“逻辑相等”的测试功能。比如:java.util.Random。
3、超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的。例如:大多数 的Set实现都是从AbstractSet继承的。还有List的实现,Map的实现。
4、类是私有的或是包级私有的,可以确定它的equals方法永运不会被调用。
5、用实例受控来确保“每个值至多只存在一个对象”的类,比如
枚举类型。这样的类逻辑相同与对象相同是一回事。
那么,什么时候应该覆盖Object.equals呢?如果类有自己特有的“逻辑相等”,并且超类没有覆盖equals来实现期望的行为,这时需要覆盖equals方法。
覆盖equals方法必须遵守的约定:
1、自反性。对于任何非null的引用值x,x.equals(x) 必须返回true。
2、对称性。对于任何非null的引用值x和y,当且仅当y.equals(x) ==true,必须有x.equals(y) == true。
3、传递性。对于任何非null的引用值x、y和z。如果y.equals(x) ==true,且y.equals(z) ==true,那么必须有z.equals(x) ==true。
4、对于任何非null的引用值x,必须有x.equals(null)==false;
书中给出几条实现高质量equals方法的诀窍:
1、使用==
caozuofu.html" target="_blank">操作符检查“参数是否为这个对象的引用”,如果是,返回true。
2、使用
instanceof操作符检查“参数是否为正确的类型”。如果是,返回true。一般所谓的正确的类型是指equals方法所在的那个类。有些时候是指该类所实现的某个
接口。
3、把参数转换成正确的类型。
4、对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。如果这些测试全部成功,返回true,否则返回false。
5、当写完equals方法后,应该问自己三个问题:它是否是对称的、传递的、一致的?这些是要编写单元测试来验证的。
最后还有几点告诫:
覆盖equals方法时总要覆盖
hashCode
不要企图让equals方法过于只能。
不要将equals声明中的Object对象替换为其它的类型。