1.简介
字符串常量池(String Pool)又称为字符串池。String类是在工作中使用频率非常高的一种对象类型,JVM为了提升性能和减小内存开销,避免字符串的重复创建,维护了一块特殊的内存空间,即字符串常量池。(由String类私有地维护)
字符串池的一个实现前提:String对象是不可变的。
2.创建字符串
1.最简单的方式:
public class test { public static void main(String[] args) { String str1 = "a"; //创建字符串 String str2 = "a"; System.out.println(str1==str2); } }
运行结果为 true
采用这种方式创建一个字符串时,JVM首先会去字符串池中查找是否存在 "a" 这个对象,如果不存在,则在字符串池中创建 "a" 这个对象,然后将池中 "a" 这个对象的引用地址返回给字符串常量str,这样str会指向池中"aaa"这个字符串对象;如果存在,则不创建任何对象,直接将池中 "a" 这个对象的地址返回,赋给字符串常量。
上述例子中,在创建str2时,字符串常量池中已经有了 "a" 这个对象,则直接把 "a" 的引用地址返回给str2,这样,str2就指向了 "a" 这个对象,即str1和str2指向了同一个对象,所以str1 == str2为true。
2.使用new关键字:
public class test { public static void main(String[] args) { String str1 = new String("a"); //创建字符串 String str2 = new String("a"); System.out.println(str1 == str2); } }
运行结果为 false
采用new关键字创建一个字符串对象时,JVM首先在字符串常量池中查找是否存在 "a" 这个字符串对象,如果存在,则不在池中再去创建 "a" 这个对象了,直接在堆中创建一个"a"字符串对象,然后将堆中的这个"a"对象的地址返回赋给引用str1,这样,str1就指向了堆中创建的这个"a"字符串对象;如果不存在,则首先在字符串常量池池中创建一个"a"字符串对象,然后再在堆中创建一个"a"字符串对象,然后将堆中这个"a"字符串对象的地址返回赋给str1引用,这样,str1指向了堆中创建的这个"a"字符串对象。
上述例子中,采用new关键字创建对象时,每次new出来的都是一个新的对象,即引用str1和str2指向的是两个不同的对象,因此语句
str1 == str2为 false。
字符串池的优缺点
字符串池的优点是避免了相同内容的字符串的创建,节省了内存,省去了创建相同字符串的时间,同时提升了性能;
另一方面,字符串池的缺点是牺牲了JVM在常量池中遍历对象所需要的时间,不过其时间成本相比而言比较低
String s = new String("ywzh")创建了几个对象的相关问题
new String("ywzh")相当于new String(String s1="ywzh"),即先要执行String s1="ywzh",然后再在堆区new一个String对象
即:
String s=new String("ywzh")创建了1或2个对象
String s="ywzh"创建了0或1个对象。
字符串拼接 + 操作符与字符串常量池
String s1 = "yw"; String s2 = "zh"; String s3 = s1 + s2;
执行上述代码时:
第一步:new一个StringBuilder;
第二步:append s1;
第三步:append s2;
第四步:调用StringBuilder的toString方法;
即:+操作符的原理是StringBuilder的append方法。
下面是一道面试题:
String s1 = "a"; String s2 = "b"; String s3 = s1+s2; String s4 = "ab"; System.out.println(s3==s4);
问题在于拼接之后的"ab"是否会放入常量池。
StringBuilder的toString方法
可以看到,返回了一个String对象,并且new好的String对象不会放进常量池里。
因此 s3 == s4 为false。
标签:常量,对象,创建,str1,字符串,new,String From: https://www.cnblogs.com/ywzh/p/17736886.html