这里首先介绍字符串池。类java.lang.String负责维护一个字符串池。可以将字符串池看作一个字符串的集合。在该字符串池中,具有相同字符序列的字符串只对应一个字符串实例对象。该字符串存放3类元素:
- 存放字符串常量
- 存放有限个字符串直接量进行“+”运算的结果
- 由类java.lang.String的成员方法intern创建的字符串实例对象
类java.lang.String的成员方法 public String intern() 首先判断当前字符串是否已经在字符串池中。
- 如果当前字符串已经在字符串池中,则返回当前字符串的引用。
- 如果当前字符串不再字符串池中而且字符串池已经含有与当前字符串相同字符次序列的字符串实例对象,则返回在字符串池中这个字符串的引用。
- 如果字符串池中不存在与当前字符串相同字符序列的字符串实例对象,则在字符串池中创建一个相同的字符串实例
用一句话归纳:对String用intern()后,在字符串池中返回一个相同值的字符串引用(在字符串池中有相同的字符串则直接返回引用,没有则创建一个再返回它的引用)
再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个
方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,
如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用,看例1就清楚了
String s0=
“kvill”;
String s1=new
String(”kvill”);
String s2=new
String(“kvill”);
System.out.println(
s0==s1 );
System.out.println(
“**********”
);
s1.intern();
s2=s2.intern();
//把常量池中“kvill”的引用赋给s2
System.out.println(
s0==s1);
System.out.println( s0==s1.intern()
);
System.out.println( s0==s2
);
结果为:
false
**********
false
//虽然执行了s1.intern(),但它的返回值没有赋给s1
true
//说明s1.intern()返回的是常量池中”kvill”的引用
true
最后我再破除一个错误的理解:
有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的Unicode字
符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的
String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:
看例2: String
s1=new String("kvill");
String
s2=s1.intern();
System.out.println( s1==s1.intern()
);
System.out.println( s1+" "+s2 );
System.out.println(
s2==s1.intern() );
结果:
false
kvill
kvill
true
在这个类中我们没有声名一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用s1.intern()后就在常量池中新添加
了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中”了。
最后用一个例子概括:
public static void main(String args[])
{
String s1 = "123456"; //字符串直接量
String s2 = "123456"; //字符串直接量
String s3 = "123"+"456"; //不是字符串直接量
String a0 = "123";
String s4 = a0 +"456"; //不是字符串直接量
String s5 = new
String("123456"); //不是字符串直接量
String s6 = s5.intern();
System.out.println("s2"+((s2==s1) ? "==" :
"!=")+"s1");
System.out.println("s3"+((s3==s1) ? "==" :
"!=")+"s1");
System.out.println("s4"+((s4==s1) ? "==" :
"!=")+"s1");
System.out.println("s5"+((s5==s1) ? "==" :
"!=")+"s1");
System.out.println("s6"+((s6==s1) ? "==" :
"!=")+"s1");
}
运行结果为:
s2 == s1;
s3 == s2;
s4!=s1;
s5!=s1;
s6==s1;
参考链接:http://blog.sina.com.cn/s/blog_69dcd5ed0101171h.html