public class StaticTest {
public static void main(String[] args){
String s1 = "java";
String s2 = "java";
String s3="ja"+"va";
System.out.println(s2==s3);//是true
String s="abc";
String ss="c";
String sss="ab";
String ssss=sss+ss;
System.out.println(ssss==s);//是false
}
}
省流版:
1.java的拼接采用的是"ja"和"va"。使用字面量拼接后,编译器会优化这个行为,拿最终拼成的结果在字符串常量池判定有无也已经存在的。如果已经存在就复用已存在的字符串因此s2和s3的地址是一致的,因为其复用了同一个字符串
2.ssss的拼接是使用引用进行拼接,也就是sss和ss,使用引用拼接相较于使用字面量,会采取StringBuilder来工作,而StringBuilder产生的对象是在堆区,而非是字符串常量池
3.总的来说:"java"的拼接结果存在于字符串常量池,而ssss的拼接结果在堆区。这是因为拼接原料的类型不同导致的,使用字面量拼接,倘若拼接结果在字符串常量池中有可复用的,则不需要创建新对象。但倘若使用引用进行拼接,那无论字符串常量池有无可复用元素,都在堆区创建一个新的String.
代码解析
public class StaticTest {
public static void main(String[] args) {
String s1 = "java";
String s2 = "java";
String s3 = "ja" + "va";
System.out.println(s2 == s3); // 第一个输出
String s = "abc";
String ss = "c";
String sss = "ab";
String ssss = sss + ss;
System.out.println(ssss == s); // 第二个输出
}
}
第一部分分析:s2 == s3
String s1 = "java";
String s2 = "java";
String s3 = "ja" + "va";
System.out.println(s2 == s3); // 第一个输出
-
字符串常量池:在 Java 中,所有字符串常量(通过字面值
"xxx"创建的字符串)都会自动存储在 字符串常量池 中。s1和s2都被赋值为字面量"java",因此它们指向常量池中的同一个对象。- 在这行代码中,
s2和s3都是字符串"java",但它们的创建方式略有不同。
-
字符串拼接:
s3是通过"ja" + "va"拼接得到的字符串。由于"ja"和"va"都是字面量,因此 Java 会在编译时将它们拼接成"java",并直接在编译时生成一个常量值"java"。- 所以,
s3也会指向常量池中的"java"。
-
==比较:s2和s3都指向常量池中的"java",因此s2 == s3为true。
第二部分分析:ssss == s
String s = "abc";
String ss = "c";
String sss = "ab";
String ssss = sss + ss;
System.out.println(ssss == s); // 第二个输出
-
字符串拼接:
- 变量
ssss是通过sss + ss拼接得到的字符串。这里sss和ss都是字符串变量,而不是常量(即它们不是字面量)。在这种情况下,字符串拼接通常在 运行时 进行。 ssss = sss + ss;在编译时无法确定拼接的结果,因为sss和ss变量的值是在运行时确定的。因此,Java 会在运行时创建一个新的StringBuilder对象来执行拼接,并生成一个新的String对象。
- 变量
-
常量池与运行时对象:
s = "abc";由于"abc"是字面量,它会直接指向常量池中的"abc"字符串。ssss则是通过运行时拼接的字符串,它不是常量池中的对象。因此,ssss是一个新的String对象,不是常量池中的"abc"。
-
==比较:ssss == s比较的是两个不同的对象:一个是常量池中的"abc",另一个是通过拼接创建的新对象。由于它们是不同的对象(即指向不同的内存位置),因此ssss == s为false。
总结
s2 == s3输出true,因为s2和s3都是编译时常量,指向字符串常量池中的"java",它们引用的是同一个对象。ssss == s输出false,因为ssss是在运行时通过拼接生成的新的字符串对象,它和常量池中的"abc"不指向同一内存位置,ssss是一个新的String对象。
输出结果:
true
false