首先我们看一段简单的代码:
package com.hydee.yss.inint.main;
public class StringTest {
public static void main(String[] args) {
String s1= "HelloWorld";
String s2 ="HelloWorld";
String s3 = "Hello" + "World";
String s4 = new String("HelloWorld");
String s5 = "Hello" + new String("World");
String s6 = s4.intern();
String s7 = "Hello";
String s8 = "World";
String s9 = s7 + s8;
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1 == s4);
System.out.println(s1 == s5);
System.out.println(s1 == s6);
System.out.println(s1 == s9);
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s5));
System.out.println(s1.equals(s6));
System.out.println(s1.equals(s9));
}
}
其运行结果如下
true
true
false
false
true
false
true
true
true
true
true
true
其实最后面六个true是很好理解的,因为比较字符串类型的时候我们需要用equals去比较两个对象的值,所以很容易得出true的结论.
那么我们来分析一下前面的六个结论(我们必须明确的一点是==比较的是引用地址):
s1 == s2 是因为String类型存在常量池的原因,我们在class文件编译时,会把字符串类型直接写死,存放在常量池中,以便复用,所以s1和s2的引用地址是相同的.
s1 == s3 虽然是动态拼接的,但是java在编译的时候会直接进行优化,这样就很好的理解了为啥相等.
s1 == s4 是因为通过new出来的字符串会在堆中重新创建一个对象,这样和s1的引用地址是完全不一样的.
s1 == s5 因为存在new 出来的部分字符串变量,这样编译器在编译的时候是不会去直接优化的,所以引用地址是不一样的.
s1 == s6 这个是因为intern()方法的缘故,他的作用就是将堆中的字符串变量放在常量池中并返回其引用地址,所以两者是相等的.
s1 == s9 这个不想等是因为连两个字符串常量在拼接的时候会创建第三个对象,这个对象的地址在堆中是不确定的.
package com.hydee.yss.inint.main;
public class StringTest {
public static void main(String[] args) {
String s1= "HelloWorld";
String s2 ="HelloWorld";
String s3 = "Hello" + "World";
String s4 = new String("HelloWorld");
String s5 = "Hello" + new String("World");
String s6 = s4.intern();
String s7 = "Hello";
String s8 = "World";
String s9 = s7 + s8;
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1 == s4);
System.out.println(s1 == s5);
System.out.println(s1 == s6);
System.out.println(s1 == s9);
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s5));
System.out.println(s1.equals(s6));
System.out.println(s1.equals(s9));
}
}
其运行结果如下
true
true
false
false
true
false
true
true
true
true
true
true
其实最后面六个true是很好理解的,因为比较字符串类型的时候我们需要用equals去比较两个对象的值,所以很容易得出true的结论.
那么我们来分析一下前面的六个结论(我们必须明确的一点是==比较的是引用地址):
s1 == s2 是因为String类型存在常量池的原因,我们在class文件编译时,会把字符串类型直接写死,存放在常量池中,以便复用,所以s1和s2的引用地址是相同的.
s1 == s3 虽然是动态拼接的,但是java在编译的时候会直接进行优化,这样就很好的理解了为啥相等.
s1 == s4 是因为通过new出来的字符串会在堆中重新创建一个对象,这样和s1的引用地址是完全不一样的.
s1 == s5 因为存在new 出来的部分字符串变量,这样编译器在编译的时候是不会去直接优化的,所以引用地址是不一样的.
s1 == s6 这个是因为intern()方法的缘故,他的作用就是将堆中的字符串变量放在常量池中并返回其引用地址,所以两者是相等的.
s1 == s9 这个不想等是因为连两个字符串常量在拼接的时候会创建第三个对象,这个对象的地址在堆中是不确定的.