为什么我下面的字符串比较代码没有显示我在 Java 中的期望


if("String ".intern().trim()=="String"){
System.out.println("Equals");
}else{
System.out.println("Unequal");
}

上面的代码显示Unequal.我不明白为什么?有人可以解释一下吗?

我不太确定你面对的是什么,但如果你想使用intern()方法比较字符串的地址,这也将起作用:

if ("String ".trim().intern() == "String") {
System.out.println("Equals");
} else {
System.out.println("Unequal");
}

您只需交换trim()intern()呼叫。

intern()搜索堆上已有的字符串并解决此问题。使用==比较字符串时,地址将相等。

为了获得更好的可视化:

Value                         Evaluates to    Address    Explanation
"String"                      "String"        1          Creates new "String"
"String "                     "String "       2          Creates new "String "
"String ".trim()              "String"        3          trim() creates new "String"
"String ".trim().intern()     "String"        1          intern() finds the already created "String"
"String ".intern()            "String "       2          intern() finds the already created "String "
"String ".intern().trim()     "String"        4          trim() creates new "String"

这也是因为trim()正在产生new String()

要自己尝试:

public class StringCompare {
public static void main(String[] args) {
System.out.println(System.identityHashCode("String"));
System.out.println(System.identityHashCode("String "));
System.out.println(System.identityHashCode("String ".trim()));
System.out.println(System.identityHashCode("String ".trim().intern()));
System.out.println(System.identityHashCode("String ".intern()));
System.out.println(System.identityHashCode("String ".intern().trim()));
}
}

将输出如下内容:

1500673861       // 1
1777631459       // 2
859434349        // 3
1500673861       // 1
1777631459       // 2
538093921        // 4

你需要知道字符串文字默认放置在字符串池中,就像

String s = "Hello";//this will be in string pool

但默认情况下,运行时通过new String(...)创建的字符串不会从此池中放置或检索。

String s2 = new String(s);// or even `new String("Hello")`
System.out.println(s == s2);// returns false, which means s2 holds different String
// object then from String pool

现在substring返回new String(...)对象,因此这意味着它们不是来自字符串池。

trim内部使用substring方法,如果

  • 指定为子字符串的范围将不同于 0,直到长度将返回new String具有指定范围字符的对象
  • 范围从 0 到字符串长度(理想情况下覆盖整个字符串)返回相同的字符串,return this;

所以在你的代码中,你试图将"String "放在字符串池中(你不必这样做,因为你正在使用已经放在池中的字符串文字"String "),然后你在这个对象上使用trim方法,所以由于有部分要修剪,它将创建并返回新的字符串, 与原始版本不同,绝对不是与字符串池不同,因此将其与"String"文字与==进行比较将返回false

"String".intern()创建一个存储在permgen或元空间中的String的不同实例,而原始实例存储在常规堆上。因此,您的比较将永远是错误的。

始终使用equals()方法比较字符串!!

尝试这样的事情:

if("String ".trim().equals("String")){
System.out.println("Equals");
}else{
System.out.println("Unequal");
}

有用的链接

  1. ==, .equals(), compareTo(), and compare()
  2. 比较字符串和字符串的一部分
  3. 我们什么时候应该使用字符串常量的字符串的实习方法(堆栈溢出示例)

最新更新