美文网首页
覆盖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