public class StringTest {  
    public static void main(String[] args) {  
        String a = “ab”; 
        System.out.println(”String a = “ab”;”);  
        String b = “cd”;
        System.out.println(”String b = “cd”;”);  
        String c = “abcd”;          String d = “ab” + “cd”;  
          
        if (d == c) {  
            System.out.println(”"ab”+”cd” 创建的对象 “加入了” 字符串池中”);  
        }  
          
        else {  
            System.out.println(”"ab”+”cd” 创建的对象 “没加入” 字符串池中”);  
        }          String e = a + “cd”;  
          
        if (e == c) {  
            System.out.println(” a  +”cd” 创建的对象 “加入了” 字符串池中”);  
        }  
         
        else {  
            System.out.println(” a  +”cd” 创建的对象 “没加入” 字符串池中”);  
        }   
    }  
}
为什么e和c指向的不是同一个对象??请高手做出解释,谢谢。。  

解决方案 »

  1.   


    如果 String e = "ab" +"cd";那么就是一个对象了,
    你这样不是
      

  2.   

    因为 "ab" + "cd" 编译器知道它一定是常量 "abcd",所以编译过程中就把它直接当作 "abcd" 了。而 a + "cd" 由于编译器不知道 a 这个变量里面是什么东西,所以这个值是运行的时候算出来的,所以是一个新的 String。
      

  3.   

    要想让他们相等就给e=c 这样e就引用了c的地址
      

  4.   

    对2楼的一点补充:
    1.通过常量表达式计算的String,计算在编译时进行,并将它作为String字面常量对待。
    2.通过连接操作得到的String(非常量表达式),连接操作是运行时进行的,会新创建对象,所以它们是不同的。
      

  5.   

    因为当编译器运行String a = “ab”; 时 编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为地址指向了数据空间的“ab”,(虽然java中没有指针,但实际上java里处处有指针,上面明显就是一个指针的应用)。
    同理 String b = “cd”; String c = “abcd”; 都在数据空间分配了空间 “cd” 空间 “abcd”,而在栈内存中分配了空间b指向 “cd”,空间c指向“abcd”
    语句 String d = “ab” + “cd”; 以为 “ab” + “cd” 是字符串相加,相当于“abcd”; 这个时候编译器有个优化,并没有在数据空间分配一个新的内存来存放“abcd”,以为它发现已经有个“abcd”存在,所以他把存在的“abcd”的地址赋值给在栈内存空间新分配的空间d,当做if (d == c)时,d和c里存放的都是数据空间中“abcd”的地址,所以d等于c,if判断成立
    容器内我们再来看看 String e = a + “cd”; 语句编译器是如何编译的
    首先一样 在栈内存空间中分配了一个新的空间 e ,而a + “cd”编译器编译时,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值(就是数据空间中“ab”的地址)和数据空间中“cd”的地址,而此时在栈空间中e的值为a + “cd”在堆空间得地址,此时在做 if (e == c) e为a + “cd”在堆空间得地址, c为“abcd”在数据空间中的地址 结果明显是不相等的!
    如果此时要得到if (e == c)为true,需要用到函数equalsif()方法。
      

  6.   

    呵呵 上面有不少地方打错了 咳 为什么在这个论坛不能对自己发出的帖子进行重新编译呢?因为当编译器运行String a = “ab”; 时编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为一个地址指向了数据空间的 “ab”,(虽然java中没有指针,但实际上java里处处有指针,上面明显就是一个指针的应用)。
    同理 String b = “cd”; String c = “abcd”; 都在数据空间分配了空间 “cd” 空间 “abcd”,而在栈内存中分配了空间b指向 “cd”,空间c指向“abcd”
    语句 String d = “ab” + “cd”; 因为 “ab” + “cd” 是字符串相加,相当于“abcd”; 这个时候编译器有个优化,并没有在数据空间分配一个新的内存空间来存放“abcd”,因为它发现已经有个“abcd”存在,所以它把存在的“abcd”的地址赋值给在栈内存空间新分配的空间d,当做if (d == c)时,d和c里存放的都是数据空间中“abcd”的地址,所以d等于c,if判断成立
    我们再来看看 String e = a + “cd”;语句,编译器是如何编译的
    首先一样 在栈内存空间中分配了一个新的空间 e ,而a + “cd”编译器编译时,a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值(就是数据空间中“ab”的地址)和数据空间中“cd”的地址,而此时在栈空间中e的值为a + “cd”在堆空间得地址,此时在做 if (e == c) e为a + “cd”在堆空间得地址, c为“abcd”在数据空间中的地址结果明显是不相等的!
    如果此时要得到if (e == c)为true,需要用到函数equals()方法。
      

  7.   

    字面常量相加在编译器就确定了,所以放在常量池了
    后者的一个对象和一个字面常量相加发生在运行期,而且是StringBuilder.toString()的结果,这个对象放在栈里面了
      

  8.   

    因为当编译器运行String a = “ab”; 时 编译器在内存数据空间(就是字符串池)中分配了一个空间,值为“ab”,而在栈内存空间中分配了一个空间,名字叫做a,它的值为地址指向了数据空间的“ab”,
    a为一个引用(因为a为一个变量,这里引用了这个变量),在java中,所用的引用都会在堆内存空间中分配一个空间,所以此时在堆内存空间中开辟了一个空间,这个空间存放了a的值
    不矛盾吗?
      

  9.   

     
    是e指向堆内存 应为是e引用了a,我说的是a为一个引用 并不是a指向堆内存
    而此时在栈空间中e的值为a + “cd”在堆空间得地址 说明e指向这个新分配的内存空间 这个空间存放了a的值 说的是新开辟的内存空间存放了a的值,就是新开辟的内存空间指向数据空间中的“ab”,实际上在堆内存中的这个内存空间里有分割成两个空间,一个指向数据空间中的“ab”,另指向数据空间中的“cd”
      

  10.   

    讨论这么多有什么用?这完全取决于编译器的行为。你可以反编译一下看一下javac做了些什么?        String a = "ab";
            String b = "cd";
            String c = "abcd";
            String d = "abcd";
            String e = (new StringBuilder(String.valueOf(a))).append("cd").toString();这是我看到的。你觉得不爽可以自己写个智能编译器,把e 也解释成 "abcd" ,不过这可能和java规范有冲突。^^
      

  11.   

    去理解一下字符串对象吧,还有就是equals() 和 == 的区别,最好了解一下内存分配
      

  12.   

    // Decompiled by DJ v3.7.7.81 Copyright 2004 Atanas Neshkov  Date: 2009-10-18 17:32:02
    // Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!
    // Decompiler options: packimports(3) 
    // Source File Name:   Test.javaimport java.io.PrintStream;public class StringTest
    {    public StringTest()
        {
        }    public static void main(String args[])
        {
            String s = "ab";
            System.out.println("String a = \"ab\";");
            String s1 = "cd";
            System.out.println("String b = \"cd\";");
            String s2 = "abcd";
            String s3 = "abcd";
            if(s3 == s2)
                System.out.println("\"ab\"+\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u52A0\u5165\u4E86\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
            else
                System.out.println("\"ab\"+\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u6CA1\u52A0\u5165\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
            String s4 = (new StringBuilder()).append(s).append("cd").toString();
            if(s4 == s2)
                System.out.println(" a  +\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u52A0\u5165\u4E86\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
            else
                System.out.println(" a  +\"cd\" \u521B\u5EFA\u7684\u5BF9\u8C61 \"\u6CA1\u52A0\u5165\" \u5B57\u7B26\u4E32\u6C60\u4E2D");
        }
    }
    我什么都不想说,贴出源代码大家都好看!