黑马程序员技术交流社区

标题: 字符串 是否相等 [打印本页]

作者: 石宗银    时间: 2011-11-5 00:13
标题: 字符串 是否相等
                                 String aa = "a" + "c";
                //aa = aa + "c";
                String bb = "a" + "c";
                //bb = bb + "c";
                System.out.println(aa == bb);

注释后,输出true; 取消注释 输出 false。

..个人理解:
           注释后:编译期运算,得到ac ,保存在 .class文件中, 再比较,是同一个引用,true
                   取消注释:aa + "c"; —— 这种以变量 连接 常量字符串时,可能jvm不能直接看懂了,,需要运行期 计算;
                     一旦进入 运行期了,,哪怕 得到 的 值 相同,但 引用 都 不同了。。都会新生一个引用。

......... 有点模糊,,请大家 释疑

作者: 刘福双    时间: 2011-11-5 08:22
给你举个小例子:
public class asd{
public static void main(String args[]){
        String aa = "a" + "c";
        aa = aa + "c";
        String bb = "a" + "c";
        bb = bb + "c";
        System.out.println(aa);
        System.out.println(bb);
        System.out.println(aa==bb);
        System.out.println(aa.equals(bb));


        }
}
==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同
这两个是不同的对象,尽管他们的内容是一样的.就像有两个人,他们的名字是相同的,但是并不是一样的人.
作者: 高美云    时间: 2011-11-5 08:27
那这个“==”应该比较两个对象的地址,两个字符串的hascode相同,比较的结果当然一样了。

作者: 吉许    时间: 2011-11-5 09:25
我试了以下代码.
                String aa="a"+"c";
                String a1=aa+"c";
                String bb="a"+"c";
                String b1=bb+"c";
                //aa.concat("c");
                //bb.concat("c");
                String cc="ac";
                String dd="a"+"c";
                System.out.println(aa.hashCode());
                System.out.println(bb.hashCode());
                System.out.println(aa.equals(bb));
                System.out.println(a1==b1);
                System.out.println(cc==dd);
对于JVM编译期运行期不是很懂,我从以下方面分析.
起初考虑到是不是JDK1.5的自动装箱的原因,试了下不是这个原因.
分析以上得出个人理解."a"+"c";的值肯定指向同一个推内存地址.把这个地址指向aa和bb.因为aa和bb指向的是同一个地址所以相等.
综合以上的代码分析问题出在aa+"c";和bb+"c"中.我认为是一个变量的引用加上一个实例对象.得到的就是不同对象.这个解释自己理解的可能有点牵强.
看了这问题也有点模糊了,大家都来发表意见,那位朋友能给出合理的解释...
作者: 吉许    时间: 2011-11-5 17:14
白天时间查了好多资料还是没找到一个合理的解释,有朋友来给个合理的解释吗?
作者: 黄健    时间: 2011-11-5 18:41
Strings computed by constant expressions  are computed at compile time and then treated as if they were literals.
Strings computed by concatenation at run time are newly created and therefore distinct.
意思大概是
通过常量表达式计算出来的字符串是在编译时计算的,因此也被看作是常量值。
通过运行时计算出来的串联字符串是重新创建的,因此它们是不同的。
字符串串联时,如果表达式中有一个不是常量表达式(String a = "abc"称为常量表达式),那么串联后的字符串是新创建的;
如果表达式中都是常量表达式,那么串联后还是常量表达式,会在String常量池中查找,如果有相同的值,则返回它的引用,不再重新创建。
作者: zhangxinxin    时间: 2011-11-5 19:43
JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在(即aa),而引用的值在程序编译期是无法确定的,即aa +"c"无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给aa。所以上面程序的结果就为false。
如果用代码方式查看它们的内存地址,可以这样写:
   String aa = "a" + "c";
         aa = aa + "c";
         String bb = "a" + "c";
         bb = bb + "c";
         System.out.println(aa == bb);
         System.out.println(System.identityHashCode(aa));
         System.out.println(System.identityHashCode(bb));


作者: 石宗银    时间: 2011-11-6 12:01
zhangxinxin 发表于 2011-11-5 19:43
JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在(即aa),而引用的值在程序编译期是无法确 ...

,,恩,好吧,,咱记住: 常量表达式能直接在编译期运算——指向相同地址; 含变量与常量表达式的运算需要在运行期运算——动态分配新地址。。
作者: 生活墨墨    时间: 2013-2-26 15:48
Response.Write("比较两个字符串是否相等<br>");
            string s1 = "abc";
            string s2 = "abc1";
            Response.Write(string.Format("字符串{0}和字符串{1}的值:",s1,s2));
            int isb = s1.CompareTo(s2);//判断两个字符串是否相等,相等则返回0,大于返回1,小于返回-1
            if (isb==0)
            {
                Response.Write("相等");
            }
            else
            {
                Response.Write("不相等");
            }
这样也行的。

作者: kaka小明    时间: 2013-4-24 22:24
吉许 发表于 2011-11-5 17:14
白天时间查了好多资料还是没找到一个合理的解释,有朋友来给个合理的解释吗? ...

注意 String字符串是“不可变字符串”,如“he”仅仅包含h和e两个字符,当想一个字符串引用追加字符串常量时,会新建一个字符串赋给String引用。如下面的1和2语句,所以二者引用地址不同
String aa = "a" + "c";
        aa = aa + "c";//---1
        String bb = "a" + "c";
        bb = bb + "c";//---2
        System.out.println(aa);
        System.out.println(bb);
        System.out.println(aa==bb);//false
        System.out.println(aa.equals(bb));
作者: changfa    时间: 2016-9-5 23:27
String是一个不可变的字符系列,一旦赋值就不能改变,所以才为false了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2