先说两个结论:
1、String str = new String("abc");

        String str = "abc";

两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。而第二种是先在栈中创建一个对 String类的对象引用变量str,然后通过符号引用去字符串常量池 里找有没有"abc",如果没有,则将"abc"存放进字符串常量池 ,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。

注意如果是 String str = new String(ab)+“c”;这里也是在堆上创建了一个新的String对象,不过常量池中会保存“c”;

2、String str = new String(abc)调用str.intern()的时候,会先查找常量池中有没有“abc”如果有直接返回,如果没有:当是JDK1.6时会在常量池中创建一个“abc”然后返回地址,当是JDK1.7及更新的版本时,会返回堆中str的引用。
趁热打铁:

点击(此处)折叠或打开

  1. String s = new String("1");
  2.         s.intern(); //这句话其实没什么意义,因为“1”已经在运行时常量池中了,返回的是运行时常量池中的地址。
  3.         String s2 = "1";
  4.         System.out.println(s == s2); //必为false

  5.         String s3 = new String("1") + new String("1");
  6.         s3.intern(); //这句话是有作用的,因为"11"从未在运行时常量池中出现过,执行了该语句之后,运行时常量池中才有"11",但是JDK1.6和JDK1.7之后的实现方式不同。
  7.         String s4 = "11";
  8.         System.out.println(s3 == s4);
运行结果如下所示:
//JDK1.6
false false
//JDK1.8
false true

点击(此处)折叠或打开

  1. String s1=new String("xy") + "z";
  2.         String s2=s1.intern(); //这句JDK1.6和JDK1.8的处理方式是不同的,JDK1.6复制一份“xyz”在运行时常量池,JDK1.8是在运行时常量池中存一份s1的引用
  3.         System.out.println( s1==s1.intern() );
  4.         System.out.println( s1+" "+s2 );
  5.         System.out.println( s2==s1.intern() );
//JDK1.6
false
xyz xyz
true
//JDK1.8
true
xyz xyz
true
String 类型的内存分配及intern方法-LMLPHPString 类型的内存分配及intern方法-LMLPHPString 类型的内存分配及intern方法-LMLPHPString 类型的内存分配及intern方法-LMLPHPString 类型的内存分配及intern方法-LMLPHPString 类型的内存分配及intern方法-LMLPHP
参考:
http://www.importnew.com/15671.html
http://blog.csdn.net/fan2012huan/article/details/50915077
http://blog.csdn.net/rj042/article/details/6871030
http://blog.csdn.net/gaopeng0071/article/details/11741027
09-22 05:01