前言
== 与 equals 不单是值的比较,== 是传递的比较操作,而 equals 是 object 提供的方法。
简述
== 操作符
== 操作符判断的是堆栈中的值。当使用操作符的是基础值类型变量,则其比较的是在栈中对应的值是否相同。
对于引用类型来说,是将堆中的地址存储到栈中,因此 == 比较的是引用类型所指向的地址是否相同。
equals 比较
object 提供了 equals 方法来警醒判断,equals 是判断堆中的值。
以 java 中的 String 实现的 equals 方法来看:
1 | public boolean equals(Object anObject) { |
可以看到传入的对象类型会转换为 object 类型,然后再以 == 判断其值是否相同。
实例
这里我们以实际案例来分析两者区别。
案例都以 java 的 String 来实现。
案例一
1 | String a = new String(); |
结果:
1 | result_1:true |
分析:
a 与 b 分别实例化,也即是开辟了两个堆空间。因此 a 与 b 所指向的内存地址是不同的,因此 a==b
的结果为 false。
而a ,b 所指向的堆内存中所存储的数据是相同(空串),调用 equals 方法 则比较的是其真正的值是否相同。因此 a.equals(b)
结果为 true。
案例二
对上面的 案例一 进行一些修改:
1 | String a = new String("hello"); |
结果
1 | result_1:true |
分析:
情况和 方案一 是相同的。这里只是为 a, b 指向的堆内存的空间中存储 "hello"
字符串(其实存储的是字符串池中的 “hello” 的地址)
案例三
1 | String a = "hello"; |
结果:
1 | result_1:true |
分析:
这次与 案例二 的结果不同。其整个过程是,String a = "hello"
字符串 a 指向字符串池中的 "hello"
的地址(栈内存中的 a 的值 为 “hello” 的地址,这里并未在堆内存中创建 a 专属的空间)。对于 String b = "hello"
由于 java 中字符串池不会重复创建相同的字符串的特点,因此 b 所指向的也是字符串池中的 "hello"
的地址。
a,b所指向的地址是相同的,因此 == 与 equals 的判断结构都是 true。
案例四
也是在 案例三的基础上进行修改:
1 | String a = "hello"; |
结果:
1 | result_1:true |
分析:
和 案例三 的情况其实是相同的。a 指向 "hello"
的地址,而 b 指向 a,也即是将 a 指向的地址赋值给 b,因此最后的结果也是 a , b 指向同一个地址。== 与 equals 的判断结构都是 true。
结论
最后在总结一下就是:
- ==操作符 对于值类型判断值是否相同,对于引用类型判断其指向的地址是否相同。
- equals 只作于于引用类型,判断其地址指向的值是否相同。
多加斟酌,注重基础,这就是我所得到的教训。