蒲公英
并非每个人都有羽化成羽化成鹰的运气,但我们至少都曾为鱼。

网上关于String和文章太多了,很多一知半解的作者都在误导大众,本人也是深受其害啊,直到今天看了这篇文章(http://www.wtoutiao.com/a/1023451.html),才拨开层层迷雾,发现JDK6和7的实现还不一样呢,发帖纪录一下。

1 一定要注意String s1=new String("c");
2 这句话的意思是,编译期在常量池就生成了字符串"c",。运行时在堆也生成了一个string对象"c",注意这两个字符串没有丝毫的关系。当执行s1.intern()时,编译器去常量池查找,发现常量池已经存在了字符串"c",所以什么都不干。这句话不会导致任何结果。可是如果是
 String s2=s1.intern();s2会直接指向常量池中的这个字符串。 3 只要是有new关键字即new String("c");都会在堆里面生成一个新的"c",这个"c"个和常量池没有关系。 
1 如果常量池中本来就有这个字符串,则调用intern方法,不会有任何后果,相当于没调用。
2 只有当常量池中不含有这个字符串的时候,调用intern方法才会导致常量池和堆产生关系,即在常量池中新建一个“字符串常量”,确切的说这个“字符串常量”不是字符串,只是指向字符串的引用,真正的字符串在堆里面。
1 重要的内容再次强调一下:
2 s.intern()方法作用:如果常量池中存在字符串s , 就会直接返回 字符串 s 在常量池中的地址, 如果常量池中没有字符串s , 会将 堆中的字符串s 的地址放入常量池中, 然后返回的是堆中字符串s 的地址,这种情况下,常量池中存储的其实不是真正的字符串,而是指向堆中真正字符串的引用。
 1 看下面的代码: (编译器在常量池已经生成了三个字符串,分别是a、b,下面详细分析运行时在对中新创建的字符串对象)       
 2         String s1=new String("a")+new String("b");
 3 //两个new分别在对中产生a、b两个字符串,加号导致的结果是产生一个StringBuffer,
 4 初始内容是a,append(b),然后调用toString方法,产生String对象"ab"
 5         String s2=s1.intern();
 6 //检查常量池,因为常量池中不存咋字符串"ab",所以把把堆中的字符串"ab"的引用放入常量池,
 7 注意常量池中存储的不是真实的string对象,而是一个引用,真正的string对象在堆中。
 8         String s3=new String("a")+new String("b");//s1同理
 9         String s4=s3.intern();//核心就是这里,s4其实指向的是s1,理解了这里就算是真正理解了jdk7的常量池了。(区别于jdk6)
10         
11         System.out.println(s2==s1);
12         System.out.println(s4==s3);
13         System.out.println(s4==s2);  
14 结果:
15 true
16 false
17 true  

之前看这篇文章(http://www.iteye.com/topic/522167)说堆里有“拘留字符串区”,现在才发现在堆里面根本没有这个东西。

以上是我的一些理解,如果有什么错误,欢迎同行批评指正。

posted on 2015-08-06 22:47  蒲公英1990  阅读(325)  评论(0编辑  收藏  举报