JAVA和+的字符串类;操作人员

JAVA和+的字符串类;操作人员,java,Java,请检查我的代码并回答,告诉我它在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 您应该使用s1.equals(s2)。=操作符比较对象是

请检查我的代码并回答,告诉我它在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

您应该使用
s1.equals(s2)
=
操作符比较对象是否相同(位于内存中相同的地址),因此它不会总是为相等的字符串返回
true

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

现在区别

String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();
s1.length()
不是编译时常量(编译时其值未知),而
8

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

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

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”
这样的字符串文本在默认情况下是插入的(它们最终会进入字符串文本池,或者从中提取,以避免重复创建同一个字符串两次)。这意味着

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

   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
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//方法java/lang/StringBuilder。”“:(Ljava/lang/String;)V
15:aload_1
16:invokevirtual#28//方法java/lang/String.length:()I
19:invokevirtual#34//方法java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
22:invokevirtual#38//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
25:astore_3
我们在哪里可以看到

10
“roushan”
正在加载字符串
12及以后用作
StringBuilder
(构造函数)
16正在计算
s1.lenbth
的下一个值
19并附加到StringBuilder
22现在使用
StringBuilder#toString
方法,我们创建表示连接文本的字符串

23并将其存储在
s3
variable

中,他不想知道equals是正确的答案,而是想知道为什么
“roushan”+8
“roushan 8”
是同一个对象,而
“roushan”+s1.length()
不是
“roushan”+8的串联在编译时完成。因此,
s1
s2
是相同的文本字符串,并放置在池中。另一方面,
s1.length()
是在运行时完成的连接。@AlexisC.,你应该把它作为一个答案发布。@Codebender我想它们已经有了各种重复:)@roushankumarSingh你不能显式地做它(引用不同于指针,并且经过组织,所以我们不必担心内存中对象的确切地址)但您可以尝试使用一个事实,即原始hashcode值很可能基于内存地址,所以您可以尝试使用
System.identityHashCode
获取其值-我们需要此方法,否则我们将从字符串类hashcode方法中重写的值,该方法不基于内存地址,而是基于字符串存储的文本。因此使用
System.identityHashCode(s1)
(与(
s2
s3
)相同)。将此答案检查为s1.length()返回8.请告诉我有关编译常量表达式的信息。打印s2和s2返回相同的值;
s1
的长度是在运行时计算的,可能在初始化和长度计算之间进行了修改。Java编译器无法分析代码,以便使用常量
8
而不是
s1.length()
StringBuilder
没有在这里使用。我观看了反编译的
.class
文件。@AndrewTobilko StringBuilder没有用于
“roushan”+8;
,但我的
javap-c
显示它用于
“roushan”+s1.length();
@Pshemo,对不起,你是对的。+1