是什么让引用比较(==)适用于Java中的某些字符串?

2022-08-31 15:08:38

我有以下代码行来比较字符串。str1 不等于 str2,这是可以理解的,因为它比较了对象引用。但是为什么 s1 等于 s2 呢?

String s1 = "abc";
String s2 = "abc";

String str1 = new String("abc");
String str2 = new String("abc");

if (s1==s2)
    System.out.println("s1==s2");           
else
    System.out.println("s1!=s2");

if (str1==str2)
    System.out.println("str1==str2");           
else
    System.out.println("str1!=str2");

if (s1==str1)
    System.out.println("str1==s1");         
else
    System.out.println("str1!=s1");

输出:

  s1==s2
  str1!=str2
  str1!=s1 

答案 1

字符串常量池实质上将缓存所有字符串文本,因此它们是下面的同一对象,这就是您看到为 执行的输出的原因。它本质上是 VM 中的一种优化,以避免在每次声明文本时都创建新的字符串对象,这可能会很快变得非常昂贵!在示例中,显式告诉 VM 创建新的字符串对象,因此为什么它是 false。s1==s2str1==str2

顺便说一句,对任何字符串调用该方法都会将其添加到常量池中,只要尚未存在等效字符串(并返回将其添加到池中的字符串)。这样做不一定是一个好主意,但是除非您确定您正在处理的字符串肯定会用作常量,否则您最终可能会创建难以跟踪的内存泄漏。intern()


答案 2

s1 和 s2 是字符串文本。创建新的 String 文本时,编译器首先检查字符串池中是否存在任何表示相同文本的文本。如果存在一个文本,编译器将返回该文本,否则编译器将创建一个新文本。

创建 String 时,编译器会从池中返回 String,因为它之前已创建。这就是原因,并且是相同的。这种行为称为实习s2s1s1s2