我运行以下代码并获得评论中显示的结果。我知道==
和.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
答案 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()
。