zoukankan      html  css  js  c++  java
  • [Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第八 ---- 九条

    这一章主要讲解Object类中的方法, Object类是所有类的父类,所以它的方法也称得上是所有对象都通用的方法

    第八条 覆盖equals时需要遵守的约定

    Object中的equals实现,就是直接对对象进行相等的比较:

        public boolean equals(Object obj) {
            return (this == obj);
        }

    那么什么时候需要覆盖equals呢?

    当你的类有自己的逻辑相等,而不是对象相等时,应该自己实现equals,比如Date和Interger,他们的相等比较不仅是对象相等,需要涉及到内部值的相等,

    // Integer的equals实现:    
        public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }
    // Date的equals实现:
        public boolean equals(Object obj) {
            return obj instanceof Date && getTime() == ((Date) obj).getTime();
        }

    equals方法的实现必须满足等价关系(温习一下数学基本概念):

    1.自反性。对于任何非null的引用值x,x.equals(x) 必须为true

    2.对称性。对于非null的x和y,x.equals(y)推导出y.equals(x)

    3.传递性。非null的xyz,x.equals(y) 并且y.equals(z),那么x.equals(z)

       这里讨论了一个典型例子。自类扩展了父类,增加了新的值组件(变量),那么equals很难在父类子类之间同时生效,比如父类的equals就缺少子类的新增变量的比较,子类的equals来比较父类,父类缺少子类新增的变量。

       文中提出了一种方法,基于组合优先于继承的原则,将子类独立出来,增加自己的值组件,并在子类中实现父类的实例,这样可以同时用equals比较这两部分

    4.一致性。任何非null的xy,只要equals的比较操作在对象中所用的信息没有改变,多少次操作得到的值应该一样

    5.非空性。一般并不需要在equals里显示的检查null == obj,因为 if (obj instanceof Integer) {}已经做了这个工作

    关于写equals的几个建议:

    1.优先使用==检查是否为这个对象的引用

    2.使用instanceof检查参数是否为正确类型

    3.equals覆盖时总要覆盖hashcode(),见第九条

    4.不要让equals太智能太复杂

    5.不要讲equals的参数改为其他类型,应该为Object

    第九条 覆盖equals时总要覆盖hashCode

    集合的操作都是基于散列的,比如从hashmap get 元素,先通过hashcode获取散列码,通过散列码找到对应的散列桶((hash bucket),然后在散列桶中通过equals找打对应的对象

    所以,如果对象有同样的equals值,他们的hashcode应该也是相等的(Object规范 JAVA SE6);

    反过来,有同样的hashCode,他们的eqauls值不一定要相同!

    在计算散列码的过程中,如果equals中没有用到的域(比如成员变量),hashCode中也最好不要!

    书中讲了一些简单的方法来获取hashCode,对于Integer,就是返回int value,boolean返回1或者0,我们看一下String的源码:

        public int hashCode() {
            int h = hash;
            if (h == 0 && value.length > 0) {
                char val[] = value;
    
                for (int i = 0; i < value.length; i++) {
                    h = 31 * h + val[i];
                }
                hash = h;
            }
            return h;
        }

    String类会将string转换为value这样一个数(private final char value[])
    所以就是对数组的每一个元素进行处理,最后获取到散列值组合

  • 相关阅读:
    webservice的cxf的客户端
    webservice用cxf发布SOAP
    webservice声明发布SOAP1.2
    webservice使用注解修改WSDL内容
    webservice获取天气信息
    结巴分词原理介绍
    Pytorch学习记录-torchtext和Pytorch的实例( 使用神经网络训练Seq2Seq代码)
    【Pandas】Pandas求某列字符串的长度,总结经验教训
    UTF-8与UTF-8 BOM
    logging.basicConfig函数
  • 原文地址:https://www.cnblogs.com/jiangz222/p/4774430.html
Copyright © 2011-2022 走看看