String中的intern方法
一.intern方法的用途
关于字符串String中的intern方法,是当前的字符对象(通过new出来的对象)可以使用intern方法从常量池中获取,
如果常量池中不存在该字符串,那么就新建一个这样的字符串放到常量池中。
使用常量池的方法一个是通过双引号定义字符串例如:String S = “1”;还有就是上面的intern方法。
二.在JDK1.6和JDK1.7中的区别
public static void main(String[] args) { String s1 = new String("1"); s1.intern(); String s2 = "1"; System.out.println(s == s2); String s3 = new String("1") + new String("1"); s3.intern(); String s4 = "11"; System.out.println(s3 == s4); }
在jdk1.6中返回false,false,jdk1.7是false,true
分析:
在JDK1.6下,StringPool在永久代,通过new关键字创建出来的有两个对象,一个在常量池,一个在堆中。
上图可以容易的看出两个s1与s2, s3与s4的地址是不一样的,所以都返回false
在JDK1.7下,由于String大量的使用导致永久代经常发生OutOfMemoryError,所以将StringPool搬到heap中
上图可以看出,为了不浪费heap的内存StringPool中的S3就直接引用了对象S3,所以S3与S4的地址是一致的
第二段代码
public static void main(String[] args) { String s1 = new String("1"); String s2 = "1"; s1.intern(); System.out.println(s1 == s2); String s3 = new String("1") + new String("1"); String s4 = "11"; s3.intern(); System.out.println(s3 == s4); }
分析第二段代码:
JDK1.6下,s1与s2,s3与s4的地址是不一致的,一个是堆中的地址,一个是常量池中的地址。
所以返回false,false。
JDK1.7下,s1与s2的地址不一致。s3创建好对象,但是s4在stringpool中创建常量,两个地址也是不一致。
所以返回false,false。
三.intern的使用技巧
适当的使用可以减少内存的消耗,每次new String都会产生一个新的对象,如果适当的使用String s=new String("1").intern();
能够适当的获取常量池的常量。
由于JDK1.6中String Pool大小限制在1009,底层是hash表加上链表组成,如果过度的使用,会导致链表过长从而导致速度变慢,所以
不是每个场景都适合使用intern方法(JDK1.7之后可以通过-XX:StringTableSize=99991设定hash表的大小)
四.总结
注意JDK1.6和JDK1.7中StringPool 的差异,以及大小的不同,合理的运用intern能给程序带来一定的好处,是系统更加健壮。
参考:https://tech.meituan.com/in_depth_understanding_string_intern.html