美文网首页
覆盖equals方法请遵守通用约定

覆盖equals方法请遵守通用约定

作者: 没走过的二丁目 | 来源:发表于2018-04-16 14:49 被阅读0次

    在覆盖equals方法的时候,你必须遵守它的通用约定,那么什么时候应该覆盖Object.equals方法呢,如果类具有自己特有的“逻辑相等”概念(不同于对象相同的概念),而且超类还没有覆盖equals以实现期望的行为,这是我们就需要覆盖equals方法。这通常属于“值类”的情形

    约定一:自反性(reflexivity)

    第一个要求仅仅说明对象必须等于其自身。很难想象会无意识地违反这一条。假如违背了这一条,然后把该类的实例添加到集合中,该集合contains方法会果断的告诉你,该集合不包含你刚添加的这个实例

    对称性(symmetry)

    例如y.equals(x)返回true 则x.equals(y) 同样返回true

    public final class CaseInsensitiveString {
        private final String s;
        public CaseInsensitiveString(String s){
            if(s == null){
                throw new NullPointerException();
            }
            this.s = s;
        }
    
        @Override
        public boolean equals(Object o) {
            if(o instanceof CaseInsensitiveString){
                return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
            }
            if(o instanceof String){
                return s.equalsIgnoreCase((String)o);
            }
            return false;
        }
    }
    

    这是一个不区分大小写的字符串,在这个类中,equals方法的意图很好,它企图与普通字符串进行互操作。假设我们有一个不区分大小写的字符串和一个普通的字符串

     CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
            String s = "polish";
           boolean result =  cis.equals(s);
    

    正如我们所预期,result为true 但是 String类中的equals方法并不知道忽略大小写,所以
    s.equals(cis) 返回的是false。假设你把不区别大写的字符串放到list中

    List<CaseInsensitiveString> list = new ArrayList<>() ;
            list.add(cis);
    

    此时 list.contains(s);会返回什么结果呢? 没人知道。一旦违反了equals约定,当其他对象面对你的对象的时候,完全不知道这些对象的行为会是什么样,那么如何才能修正这个约定呢,只需要把企图与String互操作的这段代码去掉就行了

     public boolean equals(Object o) {
            return o instanceof CaseInsensitiveString && s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
        }
    

    相关文章

      网友评论

          本文标题:覆盖equals方法请遵守通用约定

          本文链接:https://www.haomeiwen.com/subject/sdajfftx.html