JVM为了减少字符串对象的重复创建,维护了一个特殊的内存,这段内存被称为字符串常量池。并且池中的字符串的内容不重复。对于所创建的字符串对象,在字符串常量池中存放的是字符串常量对象。而new出来的字符串对象都存放在堆里。运行期调用String类的intern()方法可以向字符串常量池中动态添加对象。
String对象的创建也很讲究,关键是要明白其原理。
原理1:当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个X在String池中 找是否存在内容相同的字符串对象。如果不存在,则在池中创建一个字符串s,否则,不在池中添 加。
原理2:Java中,只要使用new关键字来创建对象,则会在堆区创建一个新的对象。
原理3:使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池 中没有就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。
原理4:使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个 String对象。
1. String name= "tom ";
2.String name =new String( "tom ");
如果你使用了第一种方式,那么当你在声明一个内容也是 "tom "的String时,如果字符串常量池中之前已存有这个字符串常量对象,它将使用串池里原来的那个内存,而不会重新分配内存,也就是说,String saname= "tom ",将会指向同一块内存 。而对于第2种方式通过new操作产生一个字符串(“tom”)时,会先去常量池中查找是否有“tom”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此“tom”对象的拷贝对象,所以String str=new String("tom "),如果常量池中原来没有"tom"则产生两个对象,否则产生一个对象。只是创建的时期不同。并且String类型是不可改变的,也就是说,当你想改变一个String对象的时候,比如name= "madding " ,那么虚拟机不会改变原来的对象,而是生成一个新的String对象,然后让name去指向它,如果原来的那个 "tom "没有任何对象去引用它,虚拟机的垃圾回收机制将接收它。