[JAVA]为什么==和equals总让新手迷惑? 详解 关系操作符 == 和 equals

关系操作符==和 类的equals方法都可以用来比较两个类是否相同,但实际用起来却经常产生令JAVA新手迷惑的结果。

先看一段示例代码:

public class HelloWorld {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //System.getProperties().list(System.out);
        String str1 = new String("Hello world!");
        String str2 = new String("Hello world!");
        System.out.println("str1==str2:"+ (str1==str2));
        System.out.println("str1.equals(str2):"+str1.equals(str2));
    }
}

输出:

str1==str2:false

str1.equals(str2):true

为什么都是对类进行比较,结果却不一样呢?当我们搞清楚两种比较方式的原理之后,问题就迎刃而解了。

1、关系操作符 == 和 !=

关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系。也就是说,==和!= 只比较两边的值是否相等。

对于JAVA来说,一切都是对象,对于对象的操作都是通过引用实现的。

str1和str2虽然内容都是"Hello world!",但却是通过两次new开辟出来了两块空间存放的,引用str1和str2指向的是不同的空间,也就是他们的地址是不一样的,所以 str==str2结果是false

2、equals方法

JAVA中所有的类都继承自Object基类,打开Object.java的源码可以看到equals方法的实现:

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

可以看到,Object.java中对equals的实现就是简单的用==对比一下。

那为什么输出了 str1.equals(str2):true 呢,是不是String中对equals进行了重写?

下面是String.java中equals方法的实现代码:

     * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(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方法,它将字符串的每一个字符进行了比较,完全相同的字符串就会输出true。

这就解释了  str1.equals(str2):true

类似的情况还有Integer、Double、Long等,读者可以自行验证

总结一下:

1、关系操作符==和!= 比较的是两边的值

2、equals方法如果未被重写则比较的是引用的地址(其实也是对值进行比较),如果被重写了那就具体情况具体分析了,诸如Integer、Double、Long等基本类型的封装类都重写了equals方法用来比较所指对象的内容

 

posted on 2018-09-14 11:15  郑晓龙  阅读(127)  评论(0编辑  收藏  举报

导航