转载

Java学习系列文章第三篇:说说equals和==

在上一篇文章中我们写过这样的代码

// 直接赋值
String str1 = "hello world";
// 构造方法
String str2 = new String("hello world");

String str3 = "hello world";

String str4 = new String("hello world");

System.out.println(str1==str2);
System.out.println(str1==str3);
System.out.println(str2==str4);

我们现在都知道了它们的输出的结果,分别是false、true和false。

==是在比较什么

在《think in java》这本书里有这样的一句话“关系操作符生成的是一个布尔的结果,它们计算的是操作数之间值的关系”。简单的说就是==号是用来比较值是否相等。

public class Main {
    public static void main(String[] args){

        int n = 30;
        int m = 30;
        
        System.out.println(n == m);
        
        String str = new String("hello world");

        String str1 = new String("hello world");

        String str2 = new String("hello world");
        
        System.out.println(str1 == str2);
        str1 = str;
        str2 = str;
        System.out.println(str1 == str2);
    }
}

上面代码的输出结果可能大家都知道是true、false和true。也许会有人会有疑问,那我们来好好的解释一下:

n == m结果为true,这个很容易理解,变量n和变量m存储的值都为3,肯定是相等的。而为什么str1和str2两次比较的结果不同?要理解这个其实只需要理解基本数据类型变量和非基本数据类型变量的区别。对于Java中的8中基本类型(4种整型byte、short、int、long,2种浮点型float、double,一个boolean型,还有一个字符型char)的变量,变量本身存储的就是值,关系操作符==进行比较时,比较的就是值本身。所以上面的 n == m的比较就是3 == 3,这个肯定结果是true啊!

对于那些引用类型的变量如str1,变量存储的并不是值本身,而是其关联对象在内存的地址。所以变量str1中存储的是它指向的对象在内存中的存储地址,并不是“值”本身,也就是说并不是直接存储的字符串"hello world"。这里面的引用和C/C++中的指针很类似。因此在用==对str1和str2进行第一次比较时,得到的结果是false。因此它们分别指向的是不同的对象,也就是说它们实际存储的内存地址不同。而在第二次比较时,都让str1和str2指向了str指向的对象,那么得到的结果毫无疑问是true。

equals又是在比较什么

equals方法是基类Object中的方法,因此对于所有继承Object的类都有该方法。先看一下下面的代码,猜猜输出的结果是什么

public class Main {

    public static void main(String[] args){;

        Object object1 = new Object();
        Object object2 = new Object();

        Object object3 = object1;

        System.out.println(object1.equals(object2));
        System.out.println(object1.equals(object3));
    }
}

上面代码的输出结果是false、true。我们来看看Object类中equals源码是什么样的:

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

在Object类中的equals方法是用来比较两个对象的引用是否相等,即是两个变量的引用是否指向同一个对象。

那下面的代码肯定会有人有疑问了,为啥输出的结果是true

public class Main {
    
    public static void main(String[] args){;

        String str1 = new String("hello");

        String str2 = new String("hello");

        System.out.println(str1.equals(str2));

    }
}

要想知道是为什么,我们查看一下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类对equals方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。

Java中其他的类例如Double、Date、Integer等,都对equals进行重写,来比较指向的对象存储的内容是否相等。

我们来总结一下:

  1. 对于==,如果作用于基本数据类型的变量,则直接比较两操作数的值是否相等;如果作用于引用类型的变量,则比较的引用变量所指向的对象的地址。
  2. 对于equals,如果类对equals没有进行重写,则比较的是引用类型的变量所指向的对象地址;诸如String类对equals方法进行了重写,比较的则是引用变量所指向的对象的内容。
  3. 注意equals方法不能作用于基本数据类型的变量

最后更新于 2018-06-29 09:21:34 并被添加「java Java学习系列文章」标签,已有 2 位童鞋阅读过。

原文  https://www.ydstudio.net/archives/66.html
正文到此结束
Loading...