string两个引用相等判断true/false原因求解

(1)String s1 = "a" +"b";
String s2 = "ab"; 
System.out.println(s1 == s2);

(2)String s = "a";
String s1 = s +"b";
String s2 = "ab"; 
System.out.println(s1 == s2);
结果
(1)true
(2)false
我不知道原因啊,为什么会是这样的结果呢,求解?

 

这个帖子有人回答了,JVM编译时等都OK了,我再复制一份我在另一个帖子的说法吧!我也希望@静夜独窗 不要在问题贴里面发这些内容了,因为这样会影响大家正常的交流,这些问题如果从点上去较真,本身就输了。

关于这个问题并不是本书的重点,我们只是通过这个小话题展开一些探讨和思考,逐步理解更多的东西。

关于@williamhoward 提到的问题,我说下,hashCode一样不代表值一样,样章当中也有提到,简单说呢String的hashCode并不是和它的地址或标志位相关的,而是与它存储的字符有关系,因为String已经重写了原始的hashCode方法,原始的hashCode值是对象头部部分二进制位的数字信息,可以在一定程度上标志对象,但不是地址,重写后的hashCode具体由用户决定,这也在Hash相关的算法中,如hashMap、HashSet、ConcurrentHashMap里面有用到,这几个对象里面用它的方式也差不多,尤其是HashSet就是对HashMap的包装,呵呵,你自己写一个算法要用它也行,细节不多说了,或许可以看下样章,里面有一些解释,呵呵!

@静夜独窗 这个问题的关键是Hotsport VM编译时的合并,然后在字节码文件中就已经是一个常量了,到真正运行时,自然string_table中是同一块空间,引用不论来自那里,保存的地址都是同一个。另外,这些内容在JDK 1.6及以下的版本是在所谓的永久代的常量池中,但是JDK 1.7以上的版本就不是了,是在堆当中,在一些字符串的处理上会有所区别,有些结果也会发生改变(书的光盘中有一个testForJDK17的代码,如果运行在1.7的环境可以试下),所以为结果较真没多大用途,它也在不断变化,这个话题只是一个小引导,我希望你学会一种不断去了解问题内在的习惯,有些东西需要迭代去思考和探讨就不断清晰了,如果一味为这个结果来扣的话,可能会扣得走火入魔,呵呵!这没多大必要,因为你我都不是虚拟机的编写者,有太多的细节,有太多的版本,有太多的改变了。

答案主要是jvm的编译对静态常量的处理

学一下javap的使用把

首先 == 比较的是地址
s1 = "a" +"b";

在java编译前,他就会变成s1="ab";
这时jvm的预加载处理,它会帮你提交处理好一些简单的程序
所以,s1和s2是相等的

(2)String s = "a";

String s1 = s +"b";

String s2 = "ab";

System.out.println(s1 == s2);
这个是因为,s是个变量,jvm不知道s的值到底是多少,所以不会在编译前有结果
在编译的时候对s2重新赋值,导致结果不一致

推广特种兵真是无所不用其极啊哈哈。。。。。。 :lol:

比较讨厌的就是这类人,打着技术的幌子,行推销的勾当.

此类帖子,如果你不是真的有疑问或者想热心帮人解答,而是故弄玄虚的广告贴,只能更让人厌烦,书有多烂不知道,但是此类的推销会让人对书的评估减分,这点是无益的.

很多技术类的论坛,基本全是被这些广告贴搞跨的,这样的例子比比皆是.

我是这么理解的,+号表示连接符,在正则中你可以看到a+b正则匹配的字符串是ab,因此String s1 = "a" +"b"; String s2 = "ab";

s1 == s2
等价于"a" + "b" = "ab"
由于+表示连接字符串,等价于"ab" = "ab"
但是S是变量,变量+字符串"b"不等于"ab"
好像JS中也是这样的,具体不清楚,可以试试~
另外,如果改成这样就可以等价了String s1 = (s +"b").intern();
想过为什么吗?再深层次的我也不懂了~呵呵,浮于表面

看一下楼主发的另一篇提问,就知道这是个书托。

饭有饭托,书有书托啊
:?: