Java中“abc”+“de”和“abc”+ de(de =“de”)之间的区别?

时间:2014-06-23 11:13:41

标签: java string

我运行以下代码并获得评论中显示的结果。我知道==.equals()之间的差异。我不明白的是为什么我的第二行代码与第三行代码的结果不同。

    String de = "de";
//  String abcde = "abc" + "de"; // abcde == "abcde" reture true
    String abcde = "abc" + de;   // abcde == "abcde" reture false;
    System.out.println();
    System.out.println(abcde=="abcde");
    System.out.println(de=="de");

在尝试调试时,我使用了javap -c命令并为第一个字符串连接获得了以下输出'code':

         Code:
 0:   ldc     #9; //String de
 2:   astore_1
 3:   new     #10; //class java/lang/StringBuilder
 6:   dup
 7:   invokespecial   #11; //Method java/lang/StringBuilder."<init>":()V
 10:  ldc     #4; //String abc
 12:  invokevirtual   #12; //Method java/lang/StringBuilder.append:(Ljava/lang
 String;)Ljava/lang/StringBuilder;
 15:  aload_1
 16:  invokevirtual   #12; //Method java/lang/StringBuilder.append:(Ljava/lang
 String;)Ljava/lang/StringBuilder;
   19:  invokevirtual   #13; //Method java/lang/StringBuilder.toString:()Ljava/l
 ng/String;
   22:  astore_2
   23:  getstatic       #14; //Field java/lang/System.out:Ljava/io/PrintStream;
   26:  invokevirtual   #15; //Method java/io/PrintStream.println:()V
   29:  getstatic       #14; //Field java/lang/System.out:Ljava/io/PrintStream;
   32:  aload_2
   33:  ldc     #16; //String abcde
   35:  if_acmpne       42
   38:  iconst_1
   39:  goto    43
   42:  iconst_0
   43:  invokevirtual   #17; //Method java/io/PrintStream.println:(Z)V
   46:  getstatic       #14; //Field java/lang/System.out:Ljava/io/PrintStream;
   49:  aload_1
   50:  ldc     #9; //String de
   52:  if_acmpne       59
   55:  iconst_1
   56:  goto    60
   59:  iconst_0
   60:  invokevirtual   #17; //Method java/io/PrintStream.println:(Z)V
   63:  return

第二个字符串连接的输出:

我对这个'代码'并不熟悉,也看不出存在这些差异的原因。那么有人可以解释为什么会出现这些差异吗?

相关post

4 个答案:

答案 0 :(得分:12)

&#34;问题&#34;只是编译器太聪明了。当它看到"abc" + "de"时,会立即将其连接到文字&#34; abcde&#34;中。但是当它看到"abc" + de时,不允许(根据Java规则)&#34;优化&#34;对于文字,但必须实现+函数,创建一个新的String对象。

字符串文字始终作为实习字符串处理,因此==将对它们起作用。

答案 1 :(得分:3)

问题与+无关,而是您要将字符串与==进行比较。

简答:使用"string".equals("string2")

在java ==中,当与对象(如字符串)一起使用时,引用等于; “这两个名字是否指向内存中的同一个对象?”

Java有一个常用字符串池,它每次都使用而不是创建一个新对象(这不是一个问题,因为字符串是不可变的),所以你的真/假问题取决于编译器是否足够聪明认识到两个字符串是否相同,因此它可以使用相同的对象。不要依赖它。

答案 2 :(得分:2)

    String de = "de"; // "de" is set during compile time and placed in the "String Pool".
//  String abcde = "abc" + "de";// abcde == "abcde" reture true -- > String reference abcde will be set to "abcde" during compilation itself. and "abcde" will be placed in the String Pool.
    String abcde = "abc" + de;         // abcde == "abcde" reture false; abcde will not be set during compilation as the value of reference de will be resolved during runtime.
    System.out.println();
    System.out.println(abcde=="abcde");// false as --> String literal "abcde" on String pool != String Object "abcde" on heap.
    System.out.println(de=="de");// true--> de points to "de" on String pool

答案 3 :(得分:1)

这是Java编译器的工件。如您所知,==比较对象引用,它不会比较它们的内容。

Java编译器实现源代码中看到的裸字符串。这就是"x"=="x"的原因,因为源代码中只有一个"x"字符串的副本,但是从值为"x"的文件中读取字符串不会== 1}}实习"x",因为它不是同一个对象。

Java编译器对于Strings上的+运算符也很聪明。它会在内部将var+"x"转换为new StringBuffer().append(var).append("x").toString()。但它也会将字符串连接在一起并将它们作为另一个字符串实例化,例如"abc"+"de"会产生实习字符串"abcde",而非new StringBuffer().append("abc").append("de").toString()