在编写代码的时候我们经常会使用 equals
和 ==
来判断两个对象是否相等,那么两者有什么区别呢,主要有以下几点区别:
- 首先的区别是,equals 是方法,而 == 是操作符;
- 对于基本类型的变量来说(如
short
、int
、long
、float
、double
),只能使用 == ,因为这些基本类型的变量没有 equals 方法。对于基本类型变量的比较,使用 == 比较, 一般比较的是它们的值。 - 对于引用类型的变量来说(例如 String 类)才有 equals 方法,因为 String 继承了 Object 类, equals 是 Object 类的通用方法。对于该类型对象的比较,默认情况下,也就是没有复写 Object 类的 equals 方法,使用 == 和 equals 比较是一样效果的,都是比较的是它们在内存中的存放地址。但是对于某些类来说,为了满足自身业务需求,可能存在 equals 方法被复写的情况,这时使用 equals 方法比较需要看具体的情况,例如 String 类,使用 equals 方法会比较它们的值;
对于上述第三点理解起来可能有点复杂,因为这里 equals 方法比较需要分两种情况来讨论,一种情况是该方法没有被重写,另外一种是该方法被重写。
- 对于 equals 方法没有被重写的情况。如果类没有重写该方法,那么默认使用的就是 Object 类的方法,以下是 Object 类的 equals 方法:
public boolean equals(Object obj) {
return (this == obj);
}
复制
从源码可以看出,里面使用的就是 == 比较,所以这种情况下比较的就是它们在内存中的存放地址。
- 对于
equals
方法被重写的情况。以 String 类为例,以下是 String 类中的 equals 方法:
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof String) {
String s = (String)other;
int count = this.count;
if (s.count != count) {
return false;
}
if (hashCode() != s.hashCode()) {
return false;
}
char[] value1 = value;
int offset1 = offset;
char[] value2 = s.value;
int offset2 = s.offset;
for (int end = offset1 + count; offset1 < end; ) {
if (value1[offset1] != value2[offset2]) {
return false;
}
offset1++;
offset2++;
}
return true;
} else {
return false;
}
}
从源码可以看出, String 类复写了 equals 方法,当使用 == 比较内存的存放地址不相等时,接下来会比较字符串的内容是否 相等,所以 String 类中的 equals 方法会比较两者的字符串内容是否一样。我们来看看下面的例子:
String a = "Hello World";
String b = new String("Hello World");
String c = b; //引用传递
System.out.println("a == b:" + a == b); //false
System.out.println("b == c:" + b == c); //true
System.out.println("a == c:" + a == c); //false
System.out.println("a.equals(b):" + a.equals(b)); //true
System.out.println("b.equals(c):" + b.equals(c)); //true
System.out.println("a.equals(c):" + a.equals(c)); //true
因为 String b 通过 new 的方式已经开辟了新的堆内存,而 String a = "Hello World" 是存放在常量池里的,两者在 Java 内存里存在放的位置是不同的,所以 a == b 为 false;而 equals 方法当两者存放的内存地址不同时,会比较两者的值,两者的值都是 "Hello World" ,所以 a.equals(b) 为 true。
public class Test {
public static void main(String[] args) {
Integer i1 = 99;
Integer i2 = 99;
System.out.println(i1 == i2); // true
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4); // false
}
}
对于 i1
和 i2
的比较,因为变量的定义方法是 i1(i2) = 10
它们的变量会置于常量区,两个变量的内存地址相同。 此时 ==
返回 true
。
那么为什么 i3
和 i4
是返回 false
呢?
这是因为 Java 中 integer 范围取值要在-128到+127 ,而我们赋的值是 128 ,此时变量并不在常量区定义。所以两个变量的内存地址不同,== 返回 false