即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

Effectivie Java语言 第二章读书学习和进阶笔记

编程语言 u012729092 15℃ 0评论

EffectiveJava笔记 第二章通用方法


1.覆盖equalsshi需要遵守的约定


i:首先来确认一下什么情况下不需要重写equals方法


a:类的实例本质上都是唯一的


b:不关心类是否提供了逻辑相等的实例


c:超类已经覆盖了equals,从父类继承来的对与子类也是合适的


d:类是私有的或者是包级私有的,介意确定的是它的equals方法永远不会被用到。(这种情况下无疑是应该覆盖这个类,一面被访问到,重写抛出异常即可)


ii:需要覆盖的情况:


a:类有自己的逻辑相等,且超类没有覆盖equals(值类)


注意:实例受控的类,比如枚举类型,逻辑相等和值在意义上是等同的


iii:实现equals方法的约束条件


a:自反性:对于任何非null的引用值,x.equals(x)必需返回TRUE


b:对称性:对于任何非null的引用值,当且仅当x.equals(y)返回TRUE时y.equals(x)返回TRUE。


例如:区分大小写的字符串和普通字符串比较,反过来就不行,所以应该在equals判断是否为相同类型


c:传递性:对于任何非null的引用值x,y,z,如果x.equals(y),y.equals(z)都返回TRUE,那么x.equals(z)返回TRUE


一个超类和两个子类的情况


d:一致性:对于任何非null的引用值x,y,只要对象的所有信息没有被修改那么多次调用就会返回一直的结果。


不可变对象需要注意:相等的对象永远相等,不相等的对象永远不相等。


e:对于任何非null的引用值,x.equals(null)必需返回false


在equals显式的和null比较是不必要的,因为instanceof 已经进行了类型比较


注意:面向对象的等价关系基本问题:无法既增加新的组件,又保留equals约定,解决这类问题的基本思路是使用复合。


iv:高质量编写equals方法的诀窍


a:使用==操作符来检查是否是这个对象本身的引用(一般对象之间比较代价比较昂贵会使用这种方法比较)


b:使用instanceof 操作符检查参数类型是否正确


c:把参数类型转换成正确的类型


d:对于关键域要进行参数检查


float以及double使用对应的Compare进行比较,其他基本类型使用==操作符,并且要注意比较顺序(比较代价高的放在后边)


f:编写完成好,要看是否实现对称,传递,一致


v:注意的一些方法


a:覆盖equals方法总得覆盖hashCode方法(否则在散列集合中才能正常运行,比如hashMap)散列集合中的对象属性改变之后无法移除,因为equals变化之后hashCode比较出现问题


b:不要想将equals方法写的太过于智能


c:不要将equals声明中的Object对象替换为其他的类型


2.覆盖equals方法的时候总要覆盖hashCode方法


我感觉去思考一下散列集合的实现,然后这个就能理解的更加清楚


i:为不相等的对象产生不不相等的散列码(可以提高查找性能)


a:把某个非零的常数值比如说17,保存在一个名为result的int值类型的常量中


b:为每一个关键域计算int类型的散列码c


boolean:f?1:0


byte,char,short,int: (int)f


long:(int)(f^(f>>>32))


float:Float.floatToBits(f)


double:Double.doubleToLongBits(f),得到long然后long再转换成int


对象:递归的调用对象的hashCode


数组:把每个元素作为单独的域来处理


c:把b中的散列码合并到result reuslt=31*reuslt+c


d:返回result


e:验证相等的实例是否有相等的散列码


ii:排除equals比较计算中没有用到的任何域,


iii:可以缓存散列码


iv:不要试图排除掉对象的关键部分来提高性能


3.始终覆盖toString


使用printf,print,z字符串联操作符(+)以及assert或者调试打印,toString会自动被调用。这里让我想起thinking in java 里边的一个死循环,就是在toString里边这样写 “String”+this 会出现无限递归调用


4.谨慎地覆盖clone


cloneable接口表明对象允许克隆,但是这个接口没有提供克隆方法,Object提供了受保护的clone,不通过反射机制是无法调用的,有时即使使用了反射也不一定调用成功


从上边的话只能说明cloneable改变了超类中受保护clone方法的行为,


i:clone方法的一般的约定


a:x.clone!=x true


b:x.clone.equals(x) true


c:x.clone().equals(x)


5.考虑使用Comparable接口


compareTo方法没有在Object类里边声明,它是Comparable接口的唯一方法,不仅能够进行等同性比较还能执行顺序比较。


类在不同类型接口的等同性测试有的依赖equals,有的依赖compareTo,


compareTo和equals的区别:


a:compare的实例化参数是泛型而非Object


b:compare的比较是为了排序不是等同性。

转载请注明:CodingBlog » Effectivie Java语言 第二章读书学习和进阶笔记

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情