黑马程序员技术交流社区

标题: 字符串的小疑惑 [打印本页]

作者: 王自强    时间: 2012-9-14 14:41
标题: 字符串的小疑惑
  1. class Test
  2. {
  3. public static void main(String[] args)
  4. {
  5. String str1 = "abcd";
  6. String str2 = "ab"+"cd";
  7. System.out.println(str2==str1);//true

  8. final String s1 = "ab";
  9. final String s2 = "cd";
  10. String s3 = s1+s2;
  11. System.out.println(s3==str1);//true

  12. String s4 = "ab";
  13. String s5 = "cd";
  14. String s6 = s4+s5;
  15. System.out.println(s6==str1);//false
  16. //这和结果为什么是false呢?
  17. }
  18. }
复制代码

作者: 尤圣回    时间: 2012-9-14 14:49
class Test

{

public static void main(String[] args)

{

String str1 = "abcd";//这是一个对象

String str2 = "ab"+"cd";连接符直接同一个对象

System.out.println(str2==str1);//true



final String s1 = "ab";

final String s2 = "cd";

String s3 = s1+s2;//  取对象池中存在的对象

System.out.println(s3==str1);//true



String s4 = "ab";

String s5 = "cd";

String s6 = s4+s5; //创建新一个对象
System.out.println(s6==str1);//false//所以对象不同

//这和结果为什么是false呢?

}

}


作者: 程金    时间: 2012-9-14 15:09
本帖最后由 程金 于 2012-9-14 18:56 编辑

很简单 (有误,待编辑) 前面s1,s2的类型是final的,编译时常量,s3就相当于是两个常量字符串连接,jvm对编译时常量字符串相加优化,编译时s3=s1+s2被替换成:s3="ab"+"cd"="abcd" ,s3指向常量池"abcd",同理,jvm对字符串的优化处理,你的str1不是对象,也是一个指向常量池中"abcd"的的引用变量,所以s3和str1相同,而后面的s6等于s4,s5相加,这是在s6是在运行期才能确定的,创建了s6对象,所以和str1不相等
作者: 陈虹旭    时间: 2012-9-14 15:22
同求,不明白啊,看来果然存在很多高手啊 ...
作者: 曹晓涵    时间: 2012-9-14 16:35
  1. /*总之,编译时确定数值的编译器会对其进行优化,加入字符串常量池,若用equals比较内容相等的,则==比较引用也会相等。
  2.       如字符串常量+字符串常量,"xx"+"xx"形式;字符串常量+基本类型形式,"xx"+14;final字符串变量+final字符串变量,final s1 + final ss2
  3. 编译时不能确定数值的编译器无法对其进行优化,会产生新的字符串引用,就算用equals比较内容相等,==比较引用也不相等。
  4.           如字符串变量+字符串变量,s4+s5;字符串变量+字符串常量,s4+"cd";字符串变量+基本数据类型,s4+14。
  5. 特殊情况,当使用getStr()方法的返回值复制给final字符串fStr变量,此时final字符串变量+字符串常量,因为需要函数调用不被优化。
  6.       此时s6=ftr+"cd",会在程序运行期动态分配一个新地址赋值给s6,故s5==s6 结果为false。
  7. String s6 = "abcd";
  8. final String fStr = getStr();
  9. String s5 = fStr+"cd";
  10. System.out.println((s5 == s6)); //false
  11. private static String getStr() {
  12.       return "ab";
  13. }
  14. */
  15. class Test
  16. {
  17.         public static void main(String[] args)
  18.         {
  19.                 /*  
  20.                 "ab"和"cd"都是常量被放在字符串池中。
  21.                 因此只创建了一个"abcd"字符串池中并将字符串"abcd"保存在字符串池中。
  22.                 当代码String str2="ab"+"cd"编译时,JVM就将常量字符串的"+"连接优化为连接后的值。
  23.                 因为编译器已经做了优化,String str2 = "ab"+"cd"和String str1="abcd"指向字符串常量池中的同一个对象。
  24.                 故str2=str1 结果为true。
  25.                 */  
  26.                 String str1 = "abcd";
  27.                 String str2 = "ab"+"cd";
  28.                 System.out.println(str2==str1);//true
  29.         /*
  30.                 对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。
  31.                 对于常量来讲,它的值是固定的,在编译期间就能被确定了,编译器对其进行优化s1+s2和"ab"+"cb"效果是一样的。
  32.                 故s3==str1结果为true。
  33.                 */
  34.                 final String s1 = "ab";
  35.                 final String s2 = "cd";
  36.                 String s3 = s1+s2;
  37.                 System.out.println(s3==str1);//true               
  38.                 /*                 
  39.                 JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的。
  40.                 因为若不是常量,s4 + s5无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给s6。
  41.                 s6=s4+s5的值是在运行时确定的,则会产生新的对象,而不是从字符串常量池中取得。
  42.                 故s6==str1 结果为false
  43.          */  
  44.                 String s4 = "ab";
  45.                 String s5 = "cd";
  46.                 String s6 = s4+s5;
  47.                 System.out.println(s6==str1);//false
  48.                
  49.         }
  50. }

复制代码





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