zoukankan      html  css  js  c++  java
  • 高质量编码--equals篇

    高质量编码系列均是出自《编写高质量代码:改善Java程序的151个建议》一书。算是自己看完以后做的一个小结。
    关于equals方法是我们经常使用的一个方法,相信很多朋友在面试复习的时候也常常碰到类似的知识点,如自定义的对象须要重写equals和hashcode方法...下面我也将提到这几点。

    覆写equals方法不要识别不出自己

    这一点我们在日常开发中可能会疏忽。
    现在我们来看一个例子,我们手头有个person类,需要通过他们的名字来判断两者是否相等,因为Object类默认equals是通过地址来判断的。
    我们重写了Person的equals方法,如下

    @Override
    public boolean equals(Object obj){
        if(obj != null && obj.instanceof Person){
            Person person = (Person)obj;
            if(person.getName() != null && this.name != null){
                return name.equalsIgnoreCase(p.getName.trim());
            }
            return false;
        }
    }
    

    我们用重写后的类来看下面的例子

    Person p1 = new Person("老张");
    Person p2 = new Person("老李 ");
    List<Person> list = new ArrayList();
    list.add(p1);
    list.add(p2);
    System.out.println(list.contains(p1));
    System.out.println(list.contains(p2));
    

    大家猜猜看结果是什么呢?

    true
    false
    

    相信有点兄嘚已经发现了,重写后的equals代码有一个问题,即存在list里的串未经过trim处理,而我们判断相等的时候却对传的person.getName()进行了trim处理,这显然是不合适的
    改进方法也很简单,我们把trim的处理放到person.getName()逻辑中。

    public String getName(){
        return name == null ? name : name.trim();
    }
    

    当然,这样的话,equals方法中也就不需要进行trim处理了,直接比较两者的名字即可。

    equals应考虑null值情景

    其实我们上面的处理已经将传入值为null的情况考虑进去了
    NPE是我们开发中很常见的一种异常,大家在开发中需要时刻提醒自己进行空值校验。说来惭愧,我在初入职场的时候犯了一个很低级的错误,稍微侃一下,工作中开发是分环境进行的,一些常用的属性我们一般都是放在配置文件中的,而要命的是,我在测试环境中进行了配置,却疏忽了配置正式环境,导致这个值上了正式取不到了,而且我在编码中并未对取出的值进行空值校验...结果我就不说了...
    反正大家以我为反面教材,不要像我一样憨憨的,相信大家不会犯少发配置这种低级错误,但在编码中多进行空值判断,因为NPE导致的线上问题还是有不少的...

    在equals中使用getClass进行类型判断,看需求

    在equals类型判断的时候我们使用的是instanceof,但我们要注意这样一种情况,如我们这里提到的Person,其他类是可以继承Person,举几个例子,如Doctor医生,Teacher老师,Coder码农,是吧,码农也是人啊,然后我们进行了这样的比较doctor.equals(coder),返回的就有可能是true,当然,如果我们有这样的需求,一个人可能表面是个医生,其实还是个码农,对吧,这样的话用instanceof也没毛病,这里只是提一下,要注意有些场景用instanceof是不合理的

    覆写equals方法必须覆写hashCode方法

    这一块好多童鞋可能都了解过,JDK API也反复强调了这一点,但是为什么要这样呢,两者之间有啥联系?
    我们先来看一个例子,Person类就是我们上面用到的那个

    Map<Person,Object> map = new HashMap<Person,Object>(){
        {
            this.put(new Person("老张"),new Object());
        }
    };
    
    System.out.println(map.containsKey(new Person("老张")));
    

    输出结果大家可能没想到

    false
    

    蛤,为啥是false,整不明白了,不是根据名字判断相等么,原因就是因为HashMap
    下面原文抄送

    因为HashMap底层处理机制是以数组的方式保存Map条目(Map Entry)的,这其中的关键是这个数组下标的处理机制:根据传入元素hashCode方法的返回值决定其数组的下标,如果该数组位置没有条目,则插入,加入到Map条目的链表中。同理,检查键是否存在也是根据哈希码确定位置,然后遍历查找键值的

    说白了就是我先根据hashCode判断,再拿equals方法进行的判断,如果hashCode判断你不在,sorry,拜拜了,直接不看equals
    那就说明,这hashCode有问题啊,我这明明要相等啊,所以我们得重写这个方法
    其实也很简单,如下

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(name).toHashCode();
    }
    

    HashCodeBuilder这个类是org.apache.commons.lang.builder包下的一个哈希码生成工具,使用方便,大家直接集成就可以用了,为啥不自己写,老大说了,哈希码生成有多种算法,自己写麻烦,事多,有工具干嘛不用[旺柴][旺柴]

    mvnrepository

    给大家提供一个网址,大家需要依赖可以上面查一下https://mvnrepository.com/

  • 相关阅读:
    CSS知识点:清除浮动
    CSS3的应用,你学会了吗?
    必须掌握的JavaScript基本知识
    一个搜索框的背后
    mybatis 中 foreach collection的三种用法
    基于Pipe的PureMVC FLEX框架的多核共享消息技术
    Flex与Java通信之HttpService
    python + eclipse + django + postgresql 开发网站(二)
    python + eclipse + django + postgresql 开发网站(一)
    [转]Python集合(set)类型的操作
  • 原文地址:https://www.cnblogs.com/lwhblog/p/12592883.html
Copyright © 2011-2022 走看看