A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 石宗银 黑马帝   /  2011-11-5 00:13  /  4601 人查看  /  10 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

                                 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不能直接看懂了,,需要运行期 计算;
                     一旦进入 运行期了,,哪怕 得到 的 值 相同,但 引用 都 不同了。。都会新生一个引用。

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

10 个回复

倒序浏览
给你举个小例子:
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是判断两个变量或实例所指向的内存空间的值是不是相同
这两个是不同的对象,尽管他们的内容是一样的.就像有两个人,他们的名字是相同的,但是并不是一样的人.
回复 使用道具 举报
那这个“==”应该比较两个对象的地址,两个字符串的hascode相同,比较的结果当然一样了。
回复 使用道具 举报
我试了以下代码.
                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"中.我认为是一个变量的引用加上一个实例对象.得到的就是不同对象.这个解释自己理解的可能有点牵强.
看了这问题也有点模糊了,大家都来发表意见,那位朋友能给出合理的解释...

评分

参与人数 1技术分 +1 收起 理由
杨玉揆 + 1

查看全部评分

回复 使用道具 举报
白天时间查了好多资料还是没找到一个合理的解释,有朋友来给个合理的解释吗?
回复 使用道具 举报
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常量池中查找,如果有相同的值,则返回它的引用,不再重新创建。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
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));

评分

参与人数 1技术分 +1 收起 理由
admin + 1 继续努力,分数快达到目标了!.

查看全部评分

回复 使用道具 举报
石宗银 黑马帝 2011-11-6 12:01:55
8#
zhangxinxin 发表于 2011-11-5 19:43
JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在(即aa),而引用的值在程序编译期是无法确 ...

,,恩,好吧,,咱记住: 常量表达式能直接在编译期运算——指向相同地址; 含变量与常量表达式的运算需要在运行期运算——动态分配新地址。。
回复 使用道具 举报
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("不相等");
            }
这样也行的。
回复 使用道具 举报
吉许 发表于 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));
回复 使用道具 举报
String是一个不可变的字符系列,一旦赋值就不能改变,所以才为false了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马