==和equals的区别

302 阅读3分钟

==和equals的区别

==的含义

1、基础数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。 2、引用数据类型:比较的是引用的地址是否相同,比如两个User对象,比较的就是指向的引用地址是否相同

equals的含义

先来看一下java.lang.Object类的实现

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

因为所有的类都是默认继承自java.lang.Object,如果子类没有重写equals方法的话,那这个equals就跟==是一样的,引用类型就是比较的应用地址,基本数据类型就是比较的值。

重写equals方法

首先equals作为一个方法,我们可以通过重新这个方法。 比如

public class User {
    private long idCard;
    private String name;

    public static void main(String[] args) {
        User user1 = new User(123456, "张三");
        User user2 = new User(123456, "张三");
        System.out.println(user1.equals(user2));  ##输出false
    }

    public User(long idCard, String name) {
        this.idCard = idCard;
        this.name = name;
    }
}

看到我们new了两个User对象,他们的两个属性都相同,但是他们指向不同的引用地址,equals方法返回false

下面我们重写equals方法,我们认为只要User对象的两个属性都相同这个两个User对象就相同。

 @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
	   if (obj == null) {
            return false;
        }
        if (obj instanceof User) {
            User tmpUser = (User) obj;
            return (this.idCard == tmpUser.idCard && this.getName().equals(((User) obj).getName())) ? true : false;
        }
        return false;
    }

同样运行上面的main方法,输出true;

可能有些童鞋注意到上面重写的equals方法里用到了字符串的equals方法。 String的equals方法有没有重写Object的equals方法呢,如果重写了又是怎么实现的? 下面是java.lang.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;
    }

我们看到,字符串的equals方法实际上是比较的每个字节是否相同,全部相同才会返回true。关于String更多的问题参考String的介绍

几个典型的重写equals方法的类

java.util.AbstractMap 我们使用的比较多的HashMap就是继承自该类。它是实现了一个深度比较,遍历每个键值对,比较每个键值对。

    public boolean equals(Object o) {
        if (o == this)
            return true;

        if (!(o instanceof Map))
            return false;
        Map<?,?> m = (Map<?,?>) o;
        if (m.size() != size())
            return false;

        try {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                K key = e.getKey();
                V value = e.getValue();
                if (value == null) {
                    if (!(m.get(key)==null && m.containsKey(key)))
                        return false;
                } else {
                    if (!value.equals(m.get(key)))
                        return false;
                }
            }
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }

        return true;
    }

同样的还有java.util.AbstractList 它是ArrayList的父类,也是循环遍历每个元素是否相等,只有所有元素相同才会返回true。

    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;

        ListIterator<E> e1 = listIterator();
        ListIterator<?> e2 = ((List<?>) o).listIterator();
        while (e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }

重写equals方法遵循的原则

1、自反性:对于任意的引用值x,x.equals(x)一定为true。 2、对称性:对于任意的引用值x 和 y,当x.equals(y)返回true,y.equals(x)也一定返回true。 3、传递性:对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回 true。 4、 一致性:对于任意的引用值x 和 y,如果用于equals比较的对象信息没有被修改,多次调用x.equals(y)要么一致地返回true,要么一致地返回false。 5、非空性:对于任意的非空引用值x,x.equals(null)一定返回false。

--------------------------end-------------------------

对你有帮助的话,记得点个赞👍

  • [六十七点五 ]

--------------------------end-------------------------