目录
1、介绍
==与equals是两个我们在编写程序的时候经常用到的语句,也是面试中经常遇到的问题,本文将详细介绍==与equals,旨在帮大家完全弄懂==与equals之间的区别。
2、JVM的内存分配
在JVM中,内存分为堆内存跟栈内存。他们二者的区别是: 当我们创建一个对象(new Object)时,会调用对象的构造函数来开辟空间,将对象数据存储到堆内存中,与此同时在栈内存中生成对应的引用,当我们在后续代码中调用的时候用的都是栈内存中的引用。值得注意的是,基本数据类型是存储在栈内存中。
3、两者的主要区别
- == 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
- equals大多时候用来比较的是两个对象的内容是否相等。
- equals 是方法,是可以被重写的,而 == 属于操作符;
equals源码:由此可知,equals底层还是由==来实现的,如果没有对equals进行重写,比较的还是它们在(栈)内存中的地址
public boolean equals(Object obj) {
return (this == obj);
}
下面通过几个简单的例子,进一步说明 :
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
最终的打印会是:
a == b:false
b == c:true
a == c:false
a.equals(b):true
b.equals(c):true
a.equals(c):true
对于引用类型的变量来说(例如 String 类)才有 equals 方法,因为 String 继承了 Object 类, equals 是 Object 类的通用方法。对于该类型对象的比较,默认情况下,也就是没有复写 Object 类的 equals 方法,使用 == 和 equals 比较是一样效果的,都是比较的是它们在内存中的存放地址。但是对于某些类来说,为了满足自身业务需求,可能存在 equals 方法被复写的情况,这时使用 equals 方法比较需要看具体的情况,例如 String 类,使用 equals 方法会比较它们的值;
String类中重写之后的equals方法源码:
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;
}
}
对于基本类型的变量来说(如 short
、 int
、 long
、 float
、 double
),只能使用 == ,因为这些基本类型的变量没有 equals 方法。对于基本类型变量的比较,使用 == 比较, 一般比较的是它们的值。
下面通过一个特殊例子,可以进一步了解:
public class Test {
public static void main(String[] args) {
Integer i1 = 10;
Integer i2 = 10;
System.out.println(i1 == i2); // true
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4); // false
}
}
此时前者==
返回 true
。
那么为什么 i3
和 i4
是返回 false
呢?
这是因为Integer对象有一个常量池,其值的范围是-128到127。当对Integer对象进行比较的时候,如果数值在-128——127以内,会直接从常量池中调用,在使用“= =”进行比较内存地址的时候,他们是相等的。但是当interger包装的数值不在常量池范围内,integer会重新new一个Integer对象,这个时候,使用”= =“进行比较就是false
4、总结:
1、==用来比较两者的栈内存地址
2、equals底层还是==,它会比较两者的栈内存地址,但是如果对它进行重写的话,需要看情况而定,例如Sting类中的equals,它不仅会比较栈内存地址,而且如果内存地址不相等,还会比较两者的内容
3、特殊情况,Integer这样的对象,它会一个常量池。