该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2012-04-09
最后修改:2012-04-29
冒着被投新手帖的风险做个汇总。不要再争论String到底创建多少个对象及相不相等的问题了,好好学习下java语言规范和java虚拟机规范才是真理吧。规范上写的很明白
此处只考虑HotSpot,其他的没用过。
如String s1 = new String("xyz"); 到底创建几个要看虚拟机的实现。而且要联系上下文 1、假设:HotSpot1.6 之前没有创建过xyz 则创建2个,之前创建过“xyz”则只创建1个 2、假设:HotSpot1.7 之前没有创建过xyz 则创建2个,之前创建过“xyz”则只创建1个 为什么请参考下边的问题2
String s3 = s1 + s2; 1、假设:hotspot1.6 则false不相等 2、假设:hotspot1.7 假设在之前常量池中没有“abcabc”时,true相等 为什么请参考下边的问题2和3
《深入Java虚拟机(原书第二版)》(基于JDK2) 即如果池中没有 需要将new一个副本放入常量池,因此在之前没有创建过时,将产生两个对象
Java虚拟机规范(Java SE 7) Java 语言需要全局统一的字符常量(这就意味着如果不同字面量(Literal)包含着相
同的码点序列,就必须引用着相同的 String 类的实例(JLS §3.10.5)) 。此外,在任意 字符串上调用 String.intern 方法,如果那个字符串是字面量的话,方法的结果应当是对 相同字面量的 String 实例的引用。因此, ("a" + "b" + "c").intern() == "abc" 必须返回 true。 为了得到字符常量,Java 虚拟机需要检查 CONSTANT_String_info 结构中的码点序 列。 如果 String.intern 方法以前曾经被某个与 CONSTANT_String_info 结构中的码 点序列一样的 String 实例调用过,那么此次字符常量获取的结果将是一个指向相同 String 实例的引用。 否则,一个新的 String 实例会被创建,它会包含着指定 CONSTANT_String_info 结构中 Unicode 码点序列;字符常量获取的结果是指向那个新 String 实例的引用。 最后,新 String 实例的 intern 方法被 Java 虚拟机自动调用。 字符常量获取的结果是指向那个新 String 实例的引用:因此 调用s3.intern() 在之前没有创建过abcabc时 总共就产生一个实例
测试用例: //oracle hotspot1.7执行(Java(TM) SE Runtime Environment (build 1.7.0-b147)) public static void testForHotSpot7() { String s1 = "abc"; String s2 = "abc"; String s3 = s1 + s2; String s4 = s1 + s2; String s5 = new String("xyz");//之前没有创建过,则创建两个对象,一个在堆中,一个在PermGen的常量池 System.out.println(s3.intern() == s3);//true System.out.println(s3.intern() == s4);//false } //oracle hotspot1.6执行(Java(TM) SE Runtime Environment (build 1.6.0_29-b11)) public static void testForHotSpot6() { String s1 = "abc"; String s2 = "abc"; String s3 = s1 + s2; String s4 = s1 + s2; System.out.println(s3.intern() == s3);//false System.out.println(s3.intern() == s4);//false String s5 = new String("xyz");//之前没有创建过,则创建两个对象 一个在堆 一个在PermGen常量池 } 具体为什么请参考问题2和问题3
1、问题:请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧 请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧 在我写下此贴之前我的测试环境仅限于xp上的hotspot(打印false),看了下回复,才发现JRockit打印了true。
那么对于这样一个简单的程序,有的jvm打印true,有的打印false,究竟谁,是有bug的版本,按我下文的论述,个人觉得打印false才是正确的。 RednaxelaFX的回复 http://www.iteye.com/topic/1112592?page=3#2216483 3、Java String 详解 - String Literal String s1 = "abc";
String s2 = "abc"; String s3 = s1 + s2; System.out.println(s3.intern() == s3); 结果为什么? http://www.iteye.com/topic/1122514#2337728 不要再讨论这种问题了,好好学习下java语言规范和java虚拟机规范 自然就明白了! 规范上写的大家一般都是遵守的,规范上没有的大家是可以乱来的。规范上写的很明白.
推荐阅读:http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html JavaSE7 javadoc http://docs.oracle.com/javase/7/docs/api/ Java语言和虚拟机规范 http://docs.oracle.com/javase/specs/index.html 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-04-09
此贴即将成为口水贴
|
|
返回顶楼 | |
发表时间:2012-04-09
freish 写道 此贴即将成为口水贴
完了 我肯定是找骂 哈哈哈 就这样吧 |
|
返回顶楼 | |
发表时间:2012-04-09
楼主最近发帖热情很高嘛!
|
|
返回顶楼 | |
发表时间:2012-04-09
最后修改:2012-04-09
guofengcn 写道 楼主最近发帖热情很高嘛!
有点空闲时间就发发贴 哈哈 其实我发了一篇不该发的帖子,发完后怕了 |
|
返回顶楼 | |
发表时间:2012-04-09
这东西弄的头晕
|
|
返回顶楼 | |
发表时间:2012-04-09
话说,这题确实是每个公司必面题~
|
|
返回顶楼 | |
发表时间:2012-04-09
还是支持一下吧。
好多看似简单的问题实际上很难说清楚,还是自己水平不够。 继续学习去。 |
|
返回顶楼 | |
发表时间:2012-04-09
caoxudong818 写道 还是支持一下吧。
好多看似简单的问题实际上很难说清楚,还是自己水平不够。 继续学习去。 我又补充了一下测试用例 ,做个汇总贴 希望对大家有用 |
|
返回顶楼 | |
发表时间:2012-04-09
freish 写道 此贴即将成为口水贴
我又补充了测试用例,呵呵,口水就口水吧 |
|
返回顶楼 | |