Java 中的 equals
和 ==
对于不同的数据类型有不同的表现,话不多少,看演示。
对于基本数据类型
对于基本数据类型来说,只能用 ==
,所以毫无疑问,这里是用来判断两个基本数据类型的值是否一致。
对于基本数据类型包装类
先来看看这种创建对象的方式:
1 | public class Demo { |
运行结果:
false
true
这里可能会有人疑问,==
不是判断两者是否相等么,那为什么结果为 false
呢?
因为这里的 Integer 是一个对象,也就是引用数据类型,里面存放的是对象在堆内存中的引用值,所以这里的 ==
只是判断两者的引用值是否相同,两者创建了两个对象,在堆内存中分别是不同的引用,由而引用值也不同,才会返回 false
。
那么我们再看一下简化版的 Integer 的创建方式:
1 | package other; |
运行结果:
true
true
false
true
equals
毫无疑问是判断值是否相同,所以结果为 true
,但是为什么第一个 ==
又为 true 了呢,而第二个 ==
还是 false。
因为在 Java 5 中,为 Integer 的操作引入了一个新的特性,用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。但适用范围只有 -128
到 +127
也就是说当自动装箱时,不会再分配内存空间,而是使用缓存中已存在的对象。
最大值 127 可以通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size
修改
这种缓存行为不仅适用于 Integer 对象。我们针对所有整数类型的类都有类似的缓存机制。Byte
、Short
、Long
、Character
都支持缓存。
其中 Byte
,Short
,Long
有固定范围: -128 到 127。对于 Character
, 范围是 0 到 127。除了 Integer
可以通过参数改变范围外,其它的都不行。
对于基本数据类型包装类而言,不论是使用哪种方式创建的,判断两者的值是否相同,务必要使用 equals
,而不要使用 ==
。
对于自定义数据类型
首先有 Person 类:
1 | public class Person { |
然后示例:
1 | public class Demo { |
这里使用 ==
的结果为 true
很容易理解,毕竟两个对象的引用不同,但是 equals
不是判断值是否相同么,我的两个id
和 name
都是一样的,为什么这里还会返回 false
呢?
Person 中我们没有写 equals 方法,根据 Java 继承的特点,Person 类继承的是 Object,所以使用的是 Object 的 equals 方法,那我们来看看 Object 的 equals 方法是怎么写的。
![image_1bo22o7qv1e801ivjhqftge18d1m.png-24.9kB][1]
原来这里的 equals 方法里用的也是 ==
,那么刚才我们用基本数据类型包装类时,为什么能判断呢,同样,我们找到 Integer 的 equals 方法。
![image_1bo22v5je88n1d611g3la3e1a1m13.png-33kB][2]
![image_1bo2315q517g21glb14ni11c9hdp2n.png-18.8kB][3]
可以看 Integer 的 equals 方法,会先判断该对象是否是一个 Integer 类的一个实例,如果不是则直接返回 false,是的话就比较他们的 value 值是否相等。
所以在我们自定义数据类型时,比较两个对象是否相同,一定要重写 equals 方法。
1 |
|
重写 equals 方法后的运行结果:
false
true
对于 String
String 也有两种创建方式,一种是 String str = new String("java");
,另一种是 String str = "java"
。
Java 为 String 类型提供了缓冲机制,当使用第二种双引号的形式创建对象时,Java 会先去字符串缓冲池中寻找内容相同的字符串,如果存在就直接拿来应用,如果不存在就创建一个新的字符串放到缓冲池中。对于第一种 new 对象的形式而言,每次都会创建一个新的对象,不会访问字符串缓冲池。
既然如此,对于 String 的 equals
和 ==
你也自然应该明白是什么结果了。
一般情况下,建议使用 String s = "abc"
方式,因为该方式采用的是字符串缓冲池机制,效率更高。
结论
在引用类型中,”==” 是比较两个引用是否指向堆内存里的同一个地址(同一个对象),而 equals 是一个普通的方法,该方法返回的结果依赖于自身的实现。
对于引用类型而言,判断两者是否相同要用 equals
方法,而不是 ==
。当然对于自定义数据类型,记得要重写 equals
方法,不然效果就等同于 ==
了。
[1]: https://cdn.jun6.net/image_1bo22o7qv1e801ivjhqftge18d1m.png
[2]: https://cdn.jun6.net/image_1bo22v5je88n1d611g3la3e1a1m13.png
[3]: https://cdn.jun6.net/image_1bo2315q517g21glb14ni11c9hdp2n.png