字符串常量池

首先我并不知道在常量池中存放的是引用还是对象,先不管它,我觉得是保存的对象,只是猜测。

在使用中String str=?;的方式来创建一个字符串对象时,虚拟机首先会对?所代表的字符串进行检查,在字符串常量池中是否有对应的字符串,如果有则将str指向该字符串对象,如果没有则会创建一个新的字符串对象并将其引用返回;

而使用String str1=new String(?);来创建时,这种方式并不会去检查字符串常量池,而是直接在堆中new一个新的String对象,值为?所代表的字符串,new出来的对象。


为什么java中会有两种方式的String呢?
因为String是一个类,只要创建一个字符串就是一个实例,就是相同的字符串也会新建一个新的对象,如果全部存在堆中则会消耗大量的内存来保存字符串(可能还不会被GC系统进行回收),所以java就运用字符串常量池来保存建立的String对象,通过虚拟机的一些运算(其实是调用在String中已经被重写的equals()方法)来判断字符串常量池中是否有相同的字符串如果有,就返回已经存在的字符串的引用;如果没有,那就在字符串常量池中新建一个字符串对象并返回它的引用。这种方式来创建字符串的话,占用的内存空间较少,并且有很高的复用性,但是牺牲了虚拟机的运算时间,算是一种时间换取空间的做法。

所以这也是为什么 String str4="java";String str5="java";str4==str5会返回true的原因;还有就是String str6="ja"+"va";str5==str6;也会返回true,那是因为在编译时期,编译器会创建一个StringBuilder,并用append()方法来将这些字符串拼接起来,最后再将StringBuilder的对象的字符串添加到字符串常量池中,并返回引用给str6;

那么如何将堆中new出来的字符串对象加入到字符串常量池中呢?
那就要用到String的intern()方法,可以做个实验来验证这个方法是否将堆中的字符串对象加到字符串常量池中:
String str2=“java”;
String str3=new String(“java”);
String str4=str3.intern();
System.out.print(str2==str4);
//如果返回true,表示成功,如果false就表示并没有添加进字符串常量池中    					             	          

我验证所得是true,即intern()方法返回的是一个该字符串在常量池中的引用。                                                                                                        


当你
String string="qwer";

String string1=new String("er");

String string2="qw"+string1;

               System.out.println(string2==string);

结果为false,说明拼接在堆中的String对象时返回的引用并不指向字符串常量池


以上文章,如有错误,请批评指正 。

猜你喜欢

转载自201610222643.iteye.com/blog/2344540