美文网首页
Java 重写 equals 注意事项

Java 重写 equals 注意事项

作者: 罗永慧 | 来源:发表于2018-11-21 16:10 被阅读4次

    自反性

    满足条件: a.equals(a) = true 保证成立;

    对称性

    满足条件:如果 a.equals(b) = true 那么 b.equals(a)必须成立

    违反规则案例

    /*自定义类**/
    public class CaseInsensitiveString {
        private final String s;
        public CaseInsensitiveString(String s) {
            this.s = Objects.requireNonNull(s);
        }
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof CaseInsensitiveString) {
                return s.equalsIgnoreCase(((CaseInsensitiveString) obj).s);
            }
            if (obj instanceof String) {
                return s.equalsIgnoreCase((String) obj);
            }
            return false;
        }
    }
    
    /*main函数**/
    public class equalsTest {
        public static void main(String[] args) {
            CaseInsensitiveString a = new CaseInsensitiveString("luoyonghui");
            String b = "luoyonghui";
            System.out.println(a.equals(b));
            System.out.println(b.equals(a));
    
            List<CaseInsensitiveString> list = new ArrayList<>();
            list.add(a);
            System.out.println(list.contains(b));
        }
    }
    

    输出日志结果

    true
    false
    false
    

    对输出结果解释如下:
    a.equals(b) 比较时,使用 CaseInsensitiveString逻辑相等的规则,通过String#equalsIgnoreCase判断结果相同。但是在b.equals(a)比较时,使用String#equals()进行逻辑相等的判断。

    /*String#equals实现代码如下**/
    public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            if (anObject instanceof String) {
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }
    

    如果不是String类型,直接返回false,所有导致上面的输出解决。同理,ArrayList#contains最终也是通过Object#equals进行逻辑判断,所以输出结果也为false

    正确的实现方案

    思路: 如果需要比对的两个对象的类型都不同,直接返回false。

      @Override
        public boolean equals(Object obj) {
            if (obj instanceof CaseInsensitiveString) {
                if (((CaseInsensitiveString) obj).s.equalsIgnoreCase(s)) {
                    return true;
                }
            }
            return false;
        }
    

    输出日志结果

    false
    false
    false
    

    相关文章

      网友评论

          本文标题:Java 重写 equals 注意事项

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