Java:== 、equals()和hashCode()

==

根据我的理解,==比较变量的值是否相等,即变量对应的栈中存放的存放的数值是不是相等的。因为基本类型的数据直接存放在栈中,所以只要值相等,==就返回true。而对于对象来说,栈中存放的是Java对中对象的地址(直接指针访问)或者句柄池中句柄的地址(句柄访问)。所以==比较的是,两边是否为同一个对象(对象的地址是否相同)。

equals()

equals方法是Object类的公开方法,具体作用根据类的不同而有所变化。

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

从源码可以看出,Object类中的equals方法其实就是==。注释上还写明:equals方法表示,一个对象“等于”另一个对象,这个方法对于非null对象具有等价性。
等价性(限于非null对象):

  • 自反性:x.equals(x)返回true。
  • 对称性:x.equals(y)与y.equals(x)的返回结果应该相同
  • 可传递性:x.equals(y)返回ture,y.equals(z)返回true,那么x.equals(z)也应该返回true。
  • 一致性:只要equals方法中要比较的信息没有修改,那么即使多次调用x.equals(y),返回的结果应该都是相同的。

重写equals方法时,一般也要重写hashcode方法,保证等价的对象要有相同的哈希码。

    // String类
    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类中,equals方法被重写了。根据源码,先使用==判断比较的两个对象是否为同一个对象。如果不是的话,再使用instanceof判断要比较的对象是否为String类型。接着比对两个字符串的长度,再比较其字符序列是否相同。

    // AbstractMap类
    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> i = entrySet().iterator();
            while (i.hasNext()) {
                Entry 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;
    }

在Abstract类中重写的equals方法,同样也是先判断比较的对象是否为同一个,然后用instanceof判断类型,用size方法判断大小。接着遍历被比较的Map实例,如果value为null,那么比较m是否有这个key,并且该key对应的value值也为null。如果value不为null,那么比较两个value存放的对象是否等价。

hashCode()

    // Object类
    public native int hashCode();

hashCode返回对象的哈希码值,它的一般规约有:

  • 多次调用同一对象时,返回的哈希码值应该相同。
  • 如果两个对象等价(调用equals方法返回true),那么它们的哈希码值一定也相同。
  • 不等价的对象的哈希码值不一定不同。尽量使其不相同。
    等价的对象的哈希码值一定相等,相同哈希码值的对象不一定等价。
    // String类
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

String类的哈希码的计算方式是:s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1]。其中s[i]是字符串的第i个字符,n是字符串的长度,^表示取幂。 (空字符串的散列值为零。)

你可能感兴趣的:(Java:== 、equals()和hashCode())