This question already has answers here:
Java String literals concatenation

(2个答案)


4年前关闭。





请检查我的代码并回答,告诉我它如何在Java技术中工作。

String s1 = "roushan8";
String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();
System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s3==s1);


结果是:

true
false
false

最佳答案

==比较引用,而不是状态。因此,如果两个引用都持有完全相同的对象==,则返回true;如果持有不同的对象,即使它们的状态相同,也将返回false。要比较对象的状态,请使用equals方法。

现在区别

String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();


s1.length()不是编译时间常数(在编译时未知其值),而8是。

因此,当编译器在编译时知道值时,它可以优化我们的代码,并在编译时将字符串连接一次,这意味着

String s2 = "roushan"+8;


将被编译为

String s2 = "roushan8";//there is no reason to repeat this concatenation every time at runtime


但对于

String s3 = "roushan"+s1.length();


s1.length()必须在运行时计算,这意味着必须将此代码编译为类似

String s3 = new StringBuilder("roushan").append(s1.length()).toString();


现在,默认情况下会像"roushan8"这样的字符串文字进行intern(它们最终会出现在String文字池中,或者从它们中取出以避免重复创建相同的字符串两次)。这意味着

String s1 = "roushan8";
String s2 = "roushan8"; // <-- that is how "roushan"+8; will be compiled


将代表来自字符串池的相同的"roushan8"常量,并由==确认。

但是在运行时使用new String()创建的字符串(并且StringBuilder#toString在内部创建new String())不会被插入。这意味着他们将不会尝试使用表示相同文本的文字,而是将创建单独的新String实例,因此,即使该实例包含相同的文本,也将其视为与String池中的对象不同的对象,后者由或s1引用。



您可以通过查看的字节码来确认

String s1 = "roushan8";
String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();


这是

   0: ldc           #19                 // String roushan8
   2: astore_1
   3: ldc           #19                 // String roushan8
   5: astore_2
   6: new           #21                 // class java/lang/StringBuilder
   9: dup
  10: ldc           #23                 // String roushan
  12: invokespecial #25                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  15: aload_1
  16: invokevirtual #28                 // Method java/lang/String.length:()I
  19: invokevirtual #34                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  22: invokevirtual #38                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  25: astore_3


我们可以看到

10 s2字符串正在加载
12及更高版本用作"roushan"中的参数(构造函数)
正在计算16个下一个StringBuilder <initialization>
19并追加到StringBuilder
22现在使用s1.lenbth方法,我们创建表示串联文本的字符串
23并将其存储在StringBuilder#toString变量中

关于java - JAVA和+运算符的字符串类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31698183/

10-14 18:13
查看更多