先看例子:
public class TestString {
public static void main(String[] args) {
String str1 = "AB";
String str2 = new String("AB");
final String str3 = "A";
final String str4 = "B";
String str5 = "A";
String str6 = "B";
String str7 = str3 + str4;
String str8 = str5 + str6;
String str9 = str3 + str6;
String str10 = "A"+ "B";
//计算结果
System.out.println(str1.equals(str2));
System.out.println(str1 == str2);
System.out.println(str1 == str7);
System.out.println(str1 == str8);
System.out.println(str1 == str9);
System.out.println(str1 == str10);
System.out.println(str1 == "AB".intern());
}
}
结果为:true false true false false true true;
结果一,二解释:
使用“==”比较是直接用实际物理内存地址去比较,而equals是基类Object类的方法,在未重写时与“==”无区别,但String类重写其方法,源码为:
public boolean equals(Object anObject) {
//比较实际物理地址
if (this == anObject) {
return true;
}
//判断anObject是否为String类型
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;
//没用fori循环
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
首先,用“==”比较,如果实际物理地址相等,即可证明所比较的必是相等。再判断类是否一致或是String的子类(String类被final所修饰必不可能有子类) ,进一步判断两个String的长度是否相等,最后将两个String变为char数组,逐个比较。注意:在比较两个char数组时所用方法。
其他结果解释:
对于String a = "123",会先去常量池中找是否有字符串“123”有则赋值(String不是原生类,所以是引用传递),没有就会new String("123")再赋值,如果使用new String(“123”),就不管常量池中是否有,都要去堆中建立一个对象。String str5 = "A" String str6 = "B" String str8 = str5 + str6相当于 String str8 = new String(str3 + str4); 在String str10 = "A"+ "B"中,会做优化调用StringBuilder(操作String,但String变量所引用地址不变),相当于String str10 = "AB"。(类似优化有byte num = 1 num += 1可以编译运行 num = num + 1不能编译运行),当final String str3 = "A" final String str4 = "B" String str7 = str3 + str4时,修饰符final会将变量放到常量池中,当str3和str4都被修饰时String str7 = "AB",否则即是String str9 = new String(str3 + str6)。