0%

==与equals的区别

前言

== 与 equals 不单是值的比较,== 是传递的比较操作,而 equals 是 object 提供的方法。

简述

== 操作符

== 操作符判断的是堆栈中的值。当使用操作符的是基础值类型变量,则其比较的是在栈中对应的值是否相同

对于引用类型来说,是将堆中的地址存储到栈中,因此 == 比较的是引用类型所指向的地址是否相同。

equals 比较

object 提供了 equals 方法来警醒判断,equals 是判断堆中的值。

以 java 中的 String 实现的 equals 方法来看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
}

可以看到传入的对象类型会转换为 object 类型,然后再以 == 判断其值是否相同。

实例

这里我们以实际案例来分析两者区别。
案例都以 java 的 String 来实现。

案例一

1
2
3
4
5
String a = new String();
String b = new String();

System.out.println("result_1:" + a.equals(b));
System.out.println("result_2:" + (a==b));

结果:

1
2
result_1:true
result_2:false

分析:
a 与 b 分别实例化,也即是开辟了两个堆空间。因此 a 与 b 所指向的内存地址是不同的,因此 a==b 的结果为 false。
而a ,b 所指向的堆内存中所存储的数据是相同(空串),调用 equals 方法 则比较的是其真正的值是否相同。因此 a.equals(b) 结果为 true。

案例二

对上面的 案例一 进行一些修改:

1
2
3
4
5
String a = new String("hello");
String b = new String("hello");

System.out.println("result_1:" + a.equals(b));
System.out.println("result_2:" + (a==b));

结果

1
2
result_1:true
result_2:false

分析:
情况和 方案一 是相同的。这里只是为 a, b 指向的堆内存的空间中存储 "hello" 字符串(其实存储的是字符串池中的 “hello” 的地址)

案例三

1
2
3
4
5
String a = "hello";
String b = "hello";

System.out.println("result_1:" + a.equals(b));
System.out.println("result_2:" + (a==b));

结果:

1
2
result_1:true
result_2:true

分析:
这次与 案例二 的结果不同。其整个过程是,String a = "hello" 字符串 a 指向字符串池中的 "hello" 的地址(栈内存中的 a 的值 为 “hello” 的地址,这里并未在堆内存中创建 a 专属的空间)。对于 String b = "hello" 由于 java 中字符串池不会重复创建相同的字符串的特点,因此 b 所指向的也是字符串池中的 "hello" 的地址。
a,b所指向的地址是相同的,因此 == 与 equals 的判断结构都是 true。

案例四

也是在 案例三的基础上进行修改:

1
2
3
4
5
String a = "hello";
String b = a;

System.out.println("result_1:" + a.equals(b));
System.out.println("result_2:" + (a==b));

结果:

1
2
result_1:true
result_2:true

分析:
和 案例三 的情况其实是相同的。a 指向 "hello" 的地址,而 b 指向 a,也即是将 a 指向的地址赋值给 b,因此最后的结果也是 a , b 指向同一个地址。== 与 equals 的判断结构都是 true。

结论

最后在总结一下就是:

  • ==操作符 对于值类型判断值是否相同,对于引用类型判断其指向的地址是否相同。
  • equals 只作于于引用类型,判断其地址指向的值是否相同。

多加斟酌,注重基础,这就是我所得到的教训。