先说两个结论:
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的引用。
趁热打铁:
-
String s = new String("1");
-
s.intern(); //这句话其实没什么意义,因为“1”已经在运行时常量池中了,返回的是运行时常量池中的地址。
-
String s2 = "1";
-
System.out.println(s == s2); //必为false
-
-
String s3 = new String("1") + new String("1");
-
s3.intern(); //这句话是有作用的,因为"11"从未在运行时常量池中出现过,执行了该语句之后,运行时常量池中才有"11",但是JDK1.6和JDK1.7之后的实现方式不同。
-
String s4 = "11";
-
System.out.println(s3 == s4);
运行结果如下所示:
//JDK1.6
false false
//JDK1.8
false true
-
String s1=new String("xy") + "z";
-
String s2=s1.intern(); //这句JDK1.6和JDK1.8的处理方式是不同的,JDK1.6复制一份“xyz”在运行时常量池,JDK1.8是在运行时常量池中存一份s1的引用
-
System.out.println( s1==s1.intern() );
-
System.out.println( s1+" "+s2 );
-
System.out.println( s2==s1.intern() );
//JDK1.6
false
xyz xyz
true
//JDK1.8
true
xyz xyz
true
参考:
http://blog.csdn.net/fan2012huan/article/details/50915077
http://blog.csdn.net/rj042/article/details/6871030
http://blog.csdn.net/gaopeng0071/article/details/11741027
阅读(1794) | 评论(0) | 转发(0) |