浅谈 == 和 equals() 的区别

在日常编写代码的过程中,== 和 equals() 经常用到。记得我刚开始写代码的时候也是弄不懂两者要在什么情况下使用,这篇文章就总结下二者的区别。

==

在 Java 中总共有 8 种基本类型(int,float,byte,double,long,short,char,boolean)。而 == 常用于比较这些基本类型的值是否相等。其实,== 比较的是基本类型的引用是否指向堆内存的同一块地址。

equals()

equals() 是对象间的比较,它比较的是堆内存中的内容是否相同。在一些子类中,如 String、Integer 等,该方法将被重写。

String 中 == 和equals() 的比较

先看一段代码:

1
2
3
4
5
6
7
8
9
String str1 = "airxiao";
String str2 = "airxiao";
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
String str2 = new String("airxiao");
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));

其输入的结果如下:

1
2
3
4
5
//以上代码输出结果
true
true
false
true

可能有人对第一个输出的结果为 true 会有点疑惑,这里要先了解下 String 的一些特性。Java 的虚拟机会在内存中单独开辟一块区域用于存储字符串对象,我们称这块区域为字符串缓冲池。我们知道创建一个字符串对象有如下两种方法:

1
2
String a = "airxiao"; // 方法1
String a = new String("airxiao"); // 方法2

对于方法 1 来说,它会先去字符串缓冲池中查找是否已经有相同的对象,如果存在的话,那么会直接把这个对象的栈内存地址直接返回给 a,如果不存在的话对象会进入字符串缓冲池再把这个对象的栈内存地址赋予给 a。

对于方法 2 来说,它会直接告诉虚拟机在堆内存中生成一个新的 String 对象,但是并不会进入字符串缓冲池。

现在,也就不难理解第一个输出结果为何为 true 了。由于在创建 str1 的时候已经在字符创缓冲池内存储了 airxiao 对象,因此在创建 str2 的时候由于字符创缓冲池内查找到了 airxiao 对象,就直接把 str1 的栈内存地址给了 str2。因此 str1 和 str2 就拥有了相同的栈内存地址。

总结

其实,equals() 是属于 Object 类中的一个方法,在 Objects 类中,equals() 方法的实现是和 == 一样的。而 String 是属于封装类型,它在内部对 equals() 方法进行了重写,equals() 的结果主要取决于重写实现。如果我们自定义了一个对象,若要比较对象是否相同,也需要对 equals() 方法进行重写。

最后,对于 == 和equals() 的区别,简单概括为 == 比较的是基本类型的引用是否指向堆内存的同一块地址,equals() 比较的是堆内存中的内容是否相同。