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

 

 

 

     

 

posted @ 2018-12-29 16:59  肥仔中意编程  阅读(17641)  评论(0编辑  收藏  举报