问题描述
String s1="Hello";
s1=s1.concat("World");
String s2="HelloWorld";
System.out.println(s1);
System.out.println(s2);
System.out.println(s2==s1); //false
在连接之后,“HelloWorld”字符串在字符串常量池中创建,我们正在创建另一个具有相同单词“HelloWorld”的字符串,那么它已经存在于字符串常量池中,因此它返回存在的引用。 那么,为什么我的代码在输出中给出错误?
String s1="Hello";
String s2="HelloWorld";
s1=s1.concat("World");
System.out.println(s1);
System.out.println(s2);
System.out.println(s2==s1);//false
String s1="Hello";
s1=s1+"World";
String s2="HelloWorld";
System.out.println(s1);
System.out.println(s2);
System.out.println(s2==s1);//false
为什么是假的?? 为什么他们指向不同的参考。 因为这个词已经存在于字符串常量池中。那么如果我们形成一个具有相同值的新字符串对象,那么它应该指向已经存在的对象。
解决方法
默认情况下,字符串具有不同的标识。字符串池中的字符串仅在字符串被 interned 时返回。
结果仅来自常量表达式的所有字符串值或字符串连接都会被自动插入。常量表达式是其值在编译时已知的表达式。这包括:
- 文字;和
-
final
原始类型或String
类的变量。
示例:
String a = "Hello" + "World"; // 'HelloWorld'
String b = "Hi" + 23 + "There"; // 'Hi23There'
final int i = 47 + 100;
String c = "Number" + i + '!'; // 'Number147!'
这在 Java Language Specification,§ 15.28 中定义。
您的用例不满足这些要求,因此您的结果是 false
。您可以通过调用 String
的 intern()
方法来触发字符串实习。如果您改写 s1 = s1.concat("World").intern();
,那么结果将是 true
。
您需要使用 equals 而不是 == ,因此您的代码必须看起来像 System.out.println(s2.equals(s1))
我们可以使用 == 运算符进行引用比较(地址比较)和 .equals() 方法进行内容比较。简单来说,== 检查两个对象是否指向相同的内存位置,而 .equals() 计算对象中值的比较。
,您正在创建两个对象 s1 和 s2 。所以当你这样做
s2==s1
您正在比较这两个对象的引用,由于两个对象是单独的,因此它们将始终返回 false。
如果比较字符串的内容,请尝试实现 .equals() 方法。
s2.equals(s1)
,s1 和 s2 是指向 2 个不同地址的 2 个不同引用。因此 s1==s2 将始终返回 false(因为地址不同)。
,这是因为 concat() 方法返回一个新的 String 对象
public String concat(String str) {
if (str.isEmpty()) {
return this;
}
return StringConcatHelper.simpleConcat(this,str);
}
如果您使用“+”运算符,这将导致您预期的输出:
String s1 = "Hello" + "World";
String s2 = "HelloWorld";
System.out.println(s1 == s2); // true
希望这有助于您的理解, 但在现实世界中,比较字符串值时总是坚持使用 .equals() :
System.out.println(s1.equals(s2));