一、代码及结果展示
String str1 = "abcdefg";
String str2 = str1;
System.out.println(str1.equals(str2));
// 输出结果:
true
String str1 = "abcdefg";
String str2 = new String("abcdefg");
System.out.println(str1.equals(str2));
// 输出结果
true
String str1 = "abcdefg";
String str2 = str1;
System.out.println(str1 == str2);
// 输出结果:
true
String str1 = "abcdefg";
String str2 = new String("abcdefg");
System.out.println(str1 == str2);
// 输出结果:
false
二、对计算机底层内存的理解
1、内存主要分为堆和栈两大部分。栈的特点是“FILO”,即先进后出,所以栈的访问速度更快。
2、当使用String str时,实质上是在栈中创建了一个变量str。
3、当对String进行赋值时,系统会先在堆内存中的常量池中查找该值是否存在,若存在则将该值的地址传给变量str,否则在堆内存中申请一块空间并存入值,再将该值的地址传给变量str。
4、new关键字是直接在堆内存中申请一块新的空间并存入值。所以图二中str1与str2的值是相同的,但其分别指向不同的地址。
三、“==”与equals方法判断字符串是否相等的区别(重点)
1、“==”:
当使用str1 == str2来判断字符串是否相等时,系统实际是通过判断两端的变量的地址是否相同来判断两个字符串是否相等的。
2、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;
}
通过查看equals方法的源代码可以发现,该方法使用的是将字符串转为字符数组,再对字符数组的每一个位置的字符进行依次比较,从而判断字符串的值本身是否相等,而不是根据地址判断。
四、两种判断是否相等的方法及输出详细解析
// 在栈中创建了一个变量str1
// 将值"abcdefg"赋值给str1,系统先在常量池中查看是否存在该值
// 显然此时常量池中不含有该值,所以申请一块空间存入该值,并将值的地址传给变量str1
String str1 = "abcdefg";
// 在栈中创建了一个变量str1
// 将str1的值赋值给str2
// 先在常量池中查看值"abcdefg"是否存在,因为上面已经创建了,所以直接将上面值的地址也传给str2
String str2 = str1;
// 此时两个变量的地址是相同的,所以两个字符串也是相同的,所以结果为true
System.out.println(str1.equals(str2));
// 输出结果:
true
// 在栈中创建了一个变量str1
// 将值"abcdefg"赋值给str1,系统先在常量池中查看是否存在该值
// 显然此时常量池中不含有该值,所以申请一块空间存入该值,并将值的地址传给变量str1
String str1 = "abcdefg";
// 在栈中创建了一个变量str1
// 将str1的值赋值给str2
// 先在常量池中查看值"abcdefg"是否存在,因为上面已经创建了,所以直接将上面值的地址也传给str2
String str2 = str1;
// 此时两个变量的地址是相同的,所以结果为true
System.out.println(str1 == str2);
// 输出结果:
true
// 这一句与上面相同,所以不再赘述
String str1 = "abcdef";
// 这一句使用了new关键字,所以传给str2的地址是一个新的地址,与str1的地址不同
String str2 = new String("abcdefg");
// 此时虽然两个字符串的地址不相同,但是其本身的值是相同的,所以结果为true
System.out.println(str1.equals(str2));
// 输出结果
true
// 这一句与上面相同,所以不再赘述
String str1 = "abcdef";
// 这一句使用了new关键字,所以传给str2的地址是一个新的地址,与str1的地址不同
String str2 = new String("abcdefg");
// 此时两个字符串的地址不相同,虽然值是相同的,但==只判断地址,所以结果为false
System.out.println(str1 == str2);
// 输出结果
false