1、设计思想
字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化:
为字符串开辟一个字符串常量池,类似于缓存区。
创建字符串常量时,判断字符串常量池中是否存在该字符串。
若存在该字符串,返回引用实例;不存在,实例化该字符串并放入池中。
2、存放在哪里
方法区存放class、static、常量信息,所以字符串常量池存放在方法区。
代码示例:
String str1 = “abc”;
String str2 = “abc”;
String str3 = “abc”;
String str4 = new String(“abc”);
String str5 = new String(“abc”);
图解:
问题1
String str4 = new String(“abc”);
创建了多少对象?
由于常量池中有“abc”,所以在堆中创建一个对象,在栈创建一个引用。
问题2
String str = new String("A"+"B") ;
创建了多少个对象?
常量池:“A”、“B”、“AB”
堆:new String(“AB”)
栈:str
问题3
String s1 = "qwer";
String s2 = new String("qwer");
System.out.println(s2.intern() == s1);// true
public String intern()
返回字符串对象的规范化表示形式。
一个初始时为空的字符串池,它由类 String 私有地维护。
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。