Java中“abc”+“de”和“abc”+ de(de =“de”)之间的区别?
我运行以下代码并获得评论中显示的结果。 我知道==
和.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."":()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
并且第二个字符串连接的输出:
我对这个“代码”并不熟悉,也看不出存在这些差异的原因。 那么有人能解释为什么会出现这些差异吗
相关文章
“问题”只是编译器太聪明了。 当它看到"abc" + "de"
它会立即将其连接到文字“abcde”中。 但是当它看到"abc" + de
,不允许(根据Java规则)将其“优化”为文字,但必须实现+
函数,创建一个新的String对象。
字符串文字总是作为实习字符串处理,因此==
将对它们起作用。
问题与+
无关,就是你要将字符串与==
进行比较。
简短回答:使用"string".equals("string2")
在java ==
中,当与对象(例如字符串)一起使用时,引用等于; “这两个名字是否指向内存中的同一个对象?”
Java有一个常用字符串池,它每次都使用而不是创建一个新对象(这不是一个问题,因为字符串是不可变的),所以你的真/假问题取决于编译器是否足够聪明才能识别出两个字符串是相同或不同的,因此它可以使用相同的对象。 不要依赖它。
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
它是Java编译器的工件。 您应该知道, ==
比较对象引用,它不会比较它们的内容。
Java编译器实现源代码中看到的裸字符串。 这就是为什么"x"=="x"
,因为只有一个"x"
字符串的副本,从源代码中获取,但是从值为"x"
的文件中读取字符串不会==
实习"x"
,因为它不是同一个对象。
Java编译器对于字符串上的+
运算符也很聪明。 它将在内部将var+"x"
转换为new StringBuffer().append(var).append("x").toString()
。 但它也会将字符串连接在一起,并将它们作为另一个字符串"abc"+"de"
,例如"abc"+"de"
将导致实习字符串"abcde"
,而不是new StringBuffer().append("abc").append("de").toString()
。