当我们看到这个面试题的时候,相信大多数同学脑海中浮现的肯定是 == 比较的是引用,equals比较的是值,但是真实情况,equal是简单的比较值吗?下面我们通过看下equals的源码来分析一下:
Equals源码分析
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;
}
首先在代码刚开始的位置使用了==,这代码如果两个对象的引用地址地址是相同的,那么默认对象的值也是相等的。
后面判断如果传入的是String 对象,那么就对String对象中的每个char进行元素比较,如果全相等,那两个对象就相等。
为什么String的equals方法之所以比较的是值?大家有没有明白了?
因此,String中equals的比较可以用下图来演示:
内存地址分配特殊的String定义
String除了通过new的形式进行定义,还可以通过等号赋值的形式:
String str = "10";
这是一种非常特殊的形式,不需要new就可以产生对象,和new有本质的区别。
String str = "10"
String str1 = "10";
String str2 = new String("10");
System.out.println(str == str1); // return true
System.out.println(str == str2); // return false
System.out.println(str.equals(str1)); // return true
System.out.println(str.equals(str2)); // return false
要想理解上面第四行为什么==也会返回True,我们需要深入理解下JVM内存分配管理方式
JVM内存分布当我们定义了一个String str = "10" , 相当于我们定义了一个字符串常量,并没有去New一个字符串对象,这种形式的赋值存在于常量池中,而不是像new一样存放在堆中。当声明这样一个字符串时,JVM会在常量池中先查找有没有对应值的对象。如果有,把它赋给当前引用,即原来的引用和现在的引用指向了同一对象。如果没有,则在常量池中新创建一个对象,以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象,而new形式创建String对象是每次调用就产生一个新的对象。
网友评论