在Java中,==
和 equals()
是用于比较对象的两种不同方法,它们有着不同的作用和用途:
-
==
运算符:-
==
运算符用于比较两个对象的引用(内存地址)是否相同。 -
如果两个引用指向内存中的同一个对象,则
==
返回true
。 -
对于基本数据类型,
==
则用于比较它们的值是否相等。
示例:
String str1 = new String("hello"); String str2 = new String("hello"); String str3 = str1; System.out.println(str1 == str2); // false,因为str1和str2引用的是不同的对象 System.out.println(str1 == str3); // true,因为str1和str3引用的是同一个对象
-
-
equals()
方法:-
equals()
方法用于比较对象的内容是否相等(逻辑相等)。 -
equals()
方法是Object
类中定义的方法,因此所有的Java类都继承了这个方法。 -
默认情况下,
equals()
方法的行为与==
运算符相同,即比较两个对象的引用是否相同。 -
但是,许多类(如
String
,Integer
等)会重写equals()
方法,以便比较对象的内容而不是引用。
示例:
String str1 = new String("hello"); String str2 = new String("hello"); System.out.println(str1.equals(str2)); // true,因为String类重写了equals方法,比较的是内容
-
误区
public class JavaBase {
public static void main(String[] args) {
//测试==和equals的区别
// int a = 128;
// Integer b = 128;
// System.out.println(a == b);
// System.out.println(b.equals(a));
// int c = 127;
// Integer d = 127;
// System.out.println(c == d);
// System.out.println(d.equals(c));
// int a1 = 128;
// Integer b1 = new Integer(128);
// System.out.println(a1 == b1);
// System.out.println(b1.equals(a1));
// int c1 = 127;
// Integer d1 = new Integer(127);
// System.out.println(c1 == d1);
// System.out.println(d1.equals(c1));
// 以上输出结果全为true
Integer a2 = -128;
Integer b2 = -128;
System.out.println(a2 == b2);//true
System.out.println(a2.equals(b2));//true
Integer a21 = -129;
Integer b21 = -129;
System.out.println(a21 == b21);//false
System.out.println(a21.equals(b21));//true
Integer a3 = new Integer(-128);
Integer b3 = new Integer(-128);
System.out.println(a3 == b3);//false
System.out.println(a3.equals(b3));//true
Integer a31 = new Integer(-129);
Integer b31= new Integer(-129);
System.out.println(a31 == b31);//false
System.out.println(a31.equals(b31));//true
}
}
对于上面的结果,为什么相同的逻辑,输出结果却不同呢?
在Java中,对于整数对象的比较,特别是
Integer
对象,存在一个称为整数缓存(Integer Cache)的机制,它对范围在-128
到127
之间的整数进行了特殊处理。这个范围是根据Java虚拟机的实现而定,通常是为了提高性能和节省内存。具体来说,当你创建一个
Integer
对象时,如果其值在-128
到127
范围内,Java会检查是否已经存在该值对应的Integer
对象。如果存在,就直接返回缓存中的对象;如果不存在,就创建一个新的Integer
对象,并将其放入缓存中。因此,对于范围在
-128
到127
之间的整数,使用==
运算符比较两个Integer
对象时,会直接比较它们的引用地址。由于它们引用的是同一个对象(如果值相同的话),因此==
比较会返回true
。这种整数缓存机制在日常开发中有助于提高性能,因为频繁使用的小整数不会反复创建新的对象,而是复用已有的对象。但是,需要注意的是,这种优化只适用于
Integer
对象,对于int
基本数据类型,直接使用==
比较的是它们的值,而不是引用。总结来说,范围在
-128
到127
之间的整数使用==
比较可以得到正确的结果,是因为它们可能引用同一个对象,这是由Java虚拟机的实现和整数缓存机制所决定的。
从堆栈存储的角度进行分析:
Heap(堆):
堆是Java中用于存储对象的主要内存区域。所有通过
new
关键字创建的对象,无论是Integer
还是其他类的实例,都存储在堆中。对于
Integer
对象,如果其值在-128
到127
范围内,Java会使用整数缓存机制(也是存储在堆里面的),从而在堆中复用已经存在的对象。Stack(栈):
栈是Java线程私有的内存区域,用于存储局部变量、方法调用和部分对象引用。
对于基本数据类型的变量(例如
int
),其值通常直接存储在栈中,而不是存储在堆中。
整数缓存与堆和栈的关系可以总结如下:
-
整数缓存机制是针对
Integer
对象在堆中的存储优化。范围在-128
到127
之间的整数会被缓存,这些对象可以在堆中被复用,而不是每次都创建新的对象。 -
当使用
==
比较两个范围内的Integer
对象时,实际上是在比较它们在堆中的引用地址。因为整数缓存使得相同值的Integer
对象可以共享同一个对象实例,所以==
比较可以返回true
。
因此,整数缓存机制的优化和堆栈的概念虽然相关,但具体来说,它主要是与堆中 Integer
对象的创建、复用及其对比方式有关,而不是直接与栈的内存分配机制有直接关系。