介绍
String类经常出现在我们的开发中,如果问你String类相关的常识,会回答String类是final修饰的,所以是不可继承的。而String类的一些深层问题需要我们深入思考。
String str = "123"和String str2 = new String("123")的区别
public static void main(String[] args) {
String str = "123";
String str2 = new String("123");
}
String str = "123":
在jdk7上jvm上有块方法区上面有个常量池,在编译期将常量池中的信息放入class文件中。如果之前有String常量值为123,那么直接将复制引用。如果没有String常量值为123,那么就创建String常量123。
String str2 = new String("123"):
在堆内存上开辟空间存放String对象值为123,如果之前在常量池已经创建了String常量值123,那么此时无需再创建常量值,如果常量池未创建,那么还需要创建String常量值123。
String字符串常量比较相等
情况1
public class StringTest {
public static void main(String[] args) {
String str1 = "123";
String str2 = "123";
System.out.println(str1 == str2);
}
}
结果:
1.png
解释:此处问题就可以深究了,到底是创建的两个String值相同,还是因为两个String对象引用相同?答案就是两个String对象的引用相同。
使用 javap -verbose StringTest.class查看
2.png
可以发现变量str1和str2都指向了常量池中第16个字符串常量。可以发现str1和str2都指向了同一个字符串常量123。过程就是先去常量池里面去查找有没有"123"这个字符串常量,没有就创建这个字符串常量,如果有这个字符串常量,那么将str1指向字符串常量的地址,同理str2。
情况2
public class StringTest {
public static void main(String[] args) {
String str1 = new String("123");
String str2 = new String("123");
System.out.println(str1 == str2);
}
}
4.png
解释:在jvm的堆上开辟一个空间用来存放String对象,str1和str2因为分别存在不同的堆上,所以比较地址不同。
字符串 " + " 的弊端
public static void main(String[] args) {
String str = "123";
System.out.println(str + "456");
}
1.png
解释:可以发现当我们使用+进行拼接字符串时,实际上给我们创建了一个StringBuilder,然后采用StringBuilder中的append方法进行拼接的。如果我们每次都写+,那么每次都创建一个StringBuilder这样明显是不合理的。所以以后字符串拼接直接写StringBuilder拼接,而不是写+。
网友评论