String常量池

看《深入理解Java虚拟机》时发现一段有意思的代码:

//jdk 1.8
    String str1=new StringBuilder("计算机").append("软件").toString();
    System.out.println(str1.intern()==str1);//true
    String str2=new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern()==str2);//false

这段代码在jdk1.6中运行得到两个false,因为jdk1.6的intern()方法将首次出现的字符串实例复制到常量池中并返回该实例的引用,而该引用与原字符串的引用(堆中的引用)不同所以得到false,jdk1.7之后,对于第一次出现的字符,intern()将位于堆中的引用复制到常量池中,之后返回的是这个引用,所以上文str1.intern()==str1得到的是true。而str2.intern()==str2得到的却是false,这是因为”java”字符串已经在StringBuilder.toString()前存入常量池了。换成其他字符得到的就是true了。

String str3=new StringBuilder("jaaaaaa").append("va").toString();
        System.out.println(str3.intern()==str3);//true

关于常量池的详细理解参见链接
http://blog.csdn.net/xsf50717/article/details/47339415

http://book.51cto.com/art/201202/317488.htm

将其中的总结摘抄如下,并做一些补充:
1. 单独使用”“引号创建的字符串都是常量,编译期就已经确定存储到常量中。
2. 使用new String(“”)创建的对象会存储到heap中,是运行期新创建的,如果常量池中没有,常量池也存放一份。所以new String()会创建两个或一个对象。
3. 使用只包含常量的字符串连接符如”aa” + “aa”创建的也是常量,编译期就能确定,已经确定存储到常量池中。
4. 使用包含变量的字符串连接符如”aa” + s1创建的对象是运行期才创建的,存储在heap中,但常量池不会存放该对象。

猜你喜欢

转载自blog.csdn.net/more_try/article/details/75309097
今日推荐