Effective Java(二)对于所有对象都通用的方法

Effective Java(二)

对于所有对象都通用的方法

Object是一个具体类,但是设计它的主要目的是为了拓展,它的所有非final方法(equals,hashCode,toString,clone和finalize)都有明确的通用约定,因为它们被设计成是要被覆盖的。所以,任何一个类在覆盖这些方法的时候,都有责任遵守这些规定。

1. equals

在如下情况下不覆盖或者是确保永远不被调用

  1. 类的每个实例本质上是唯一的
  2. 不关心类是否提供了“逻辑相等”的测试功能
  3. 超类已经覆盖了equals,从超类继承而来的行为对子类也是合适的
  4. 类是私有的或是包级私有的,确定equals方法永远不会被调用,这种情况下应该覆盖equals方法,以防它会被意外调用

应该覆盖equals的情况:

  1. 需要知道逻辑上是否相等,而不是引用是否指向同一个对象的时候。类为“值类”

覆盖equals时所需要满足的条件:

  1. 自反性:每个对象都等于自己
  2. 对称性:两个对象双方相等。
    在编写自己的类的时候要特别注意,本类重写的equals操作默认是知道其他复合类的信息的,但是被复合类可能不知道本类的信息。这样就很容易不满足传递性,导致实现出现异常。
  3. 传递性:多个对象相等的时候,相等可传递。
    我们无法在扩展可实例化类的同时,既增加新的值组件,同时又保留equals约定,除非放弃面向对象的抽象所带来的优势。
    如果使用getClass测试来替换instanceOf测试,可以扩展可实例化类和增加新的值组件,但是这样操作所造成的结果是不可接受的:
    getClass判断的是类的绝对类型,而instanceOf判断的是类的类型以及是否继承于相同的父类。所以getClass要更加严格。而“里氏替换原则”认为一个类型的任何重要属性也将适用于它的子类型。如果父类采用的是getClass方法写成的equals方法,则其子类无论值是什么,都将会返回false。
    权宜之计:使用复合而不是继承。
  4. 一致性:无论多少次比较,返回结果要一致。
    无论类是否可变,都不要使equals方法依赖于不可靠的资源,比如对于IP地址,时间的依赖。
  5. 对于所有非null的引用,绝不等于null;
    没有必要对于equals方法提供显式的判断非空测试,而应该在进行转换之前(参数一定是Object类型)使用instanceOf检查是否为正确的类型。

实现高质量equals方法的诀窍:

  1. 使用“==”操作符检查“参数是否为这个对象的引用”,这是一种性能优化,如果比较操作很昂贵,就值得这么去做。
  2. 使用“instanceOf”检查“参数是否是正确的类型”
  3. 使用instanceOf检查之后,把对象转换为正确的类型。
  4. 对于每个关键域,检查参数中的域是否与该对象中的域相匹配。
  5. 编写完equals方法之后,问自己:是否满足:对称性,传递性,一致性。

告诫:

  1. 覆盖equals时总要覆盖hashCode
  2. 不要企图使equals太智能
  3. 不要将声明中的Object对象替换成其他的类型。

2. 覆盖equals时总要覆盖hashCode

不这样做的话就会违反Object.hashCode的通用规约:相等的对象一定有相同的散列码(即使是在逻辑上相等,从而导致该类无法结合所有基于散列的集合一起工作,包括HashMap,HashSet,Hashtable等。

始终要覆盖toString

提供一个“简洁的,但信息丰富,并且易于阅读的表达方式”,无论是否为toString指定格式,都要在文档注释里为toString返回值中包含的所有信息,提供一种编程式的访问途径

谨慎覆盖clone

如果真的要copy对象,可以使用拷贝构造器(copy constructor)或拷贝工厂(copy factory)。比起调用clone方法,这样做风险更小。

考虑实现comparable接口

compareTo方法不但允许进行简单的等同性比较,而且允许执行顺序比较,除此之外,它与Object的equals方法具有相似的特征,他还是个泛型。类实现了Comparable接口,就表明他的实例具有内在的排序关系(natural ordering)。

comparable接口用于排序,所有值类型的类都可以考虑实现Comparable接口。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值