比较字符串

为了比较 Strings 的相等性,你应该使用 String 对象的 equalsequalsIgnoreCase 方法。

例如,以下代码段将确定 String 的两个实例是否在所有字符上相等:

String firstString = "Test123";
String secondString = "Test" + 123;

if (firstString.equals(secondString)) {
   // Both Strings have the same content.
}

现场演示

这个例子将比较它们,与它们的情况无关:

String firstString = "Test123";
String secondString = "TEST123";

if (firstString.equalsIgnoreCase(secondString)) {
    // Both Strings are equal, ignoring the case of the individual characters.
}

现场演示

请注意, equalsIgnoreCase 不允许你指定 Locale。例如,如果你用英语比较两个单词 TakiTAKI,它们是相等的; 然而,在土耳其语中他们是不同的(土耳其语,小写的 Iı)。对于这样的情况,使用 Locale 将两个字符串转换为小写(或大写),然后与 equals 进行比较是解决方案。

String firstString = "Taki";
String secondString = "TAKI";

System.out.println(firstString.equalsIgnoreCase(secondString)); //prints true

Locale locale = Locale.forLanguageTag("tr-TR");

System.out.println(firstString.toLowerCase(locale).equals(
                   secondString.toLowerCase(locale))); //prints false

现场演示

不要使用==运算符来比较字符串

除非你能保证所有字符串都已被实现(见下文),否则不应该使用 ==!= 运算符来比较字符串。这些运算符实际上测试引用,并且因为多个 String 对象可以表示相同的 String,所以这可能给出错误的答案。

相反,使用 String.equals(Object) 方法,它将根据字符串的值比较 String 对象。有关详细说明,请参阅陷阱:使用==来比较字符串

在 switch 语句中比较字符串

Version => Java SE 7

从 Java 1.7 开始,可以将一个 String 变量与 switch 语句中的文字进行比较。确保 String 不为 null,否则它将始终抛出 NullPointerException 。使用 String.equals 比较值,即区分大小写。

String stringToSwitch = "A";

switch (stringToSwitch) {
    case "a":
        System.out.println("a");
        break;
    case "A":
        System.out.println("A"); //the code goes here
        break;
    case "B":
        System.out.println("B");
        break;
    default:
        break;
}

现场演示

将字符串与常量值进行比较

String 与常量值进行比较时,可以将常数值放在 equals 的左侧,以确保如果另一个字符串是 null,则不会得到 NullPointerException

"baz".equals(foo)

如果 foonull,则 foo.equals("baz") 将投掷 NullPointerException,而 "baz".equals(foo) 将评估为 false

Version => Java SE 7

更可读的替代方法是使用 Objects.equals(),它对两个参数进行空检查:Objects.equals(foo, "baz")

注意: 关于一般是否更好地避免 NullPointerExceptions,或者让它们发生然后解决根本原因是否更好是有争议的;请看这里这里 。当然,将撤销策略称为最佳实践是不合理的。)

字符串排序

String 类使用 String.compareTo 方法实现 Comparable<String>(如本例开头所述)。这使得 String 对象的自然排序区分大小写。String 类提供了一个名为 CASE_INSENSITIVE_ORDERComparator<String> 常量,适用于不区分大小写的排序。

与实习字符串比较

Java 语言规范( JLS 3.10.6 )声明如下:

“此外,字符串文字总是引用类 String 的相同实例。这是因为字符串文字 - 或者更常见的是作为常量表达式值的字符串 - *被实现,*以便使用方法 String.intern 共享唯一实例。 “

这意味着使用 == 比较对两个字符串文字的引用是安全的。此外,对于使用 String.intern() 方法生成的 String 对象的引用也是如此。

例如:

String strObj = new String("Hello!");
String str = "Hello!";

// The two string references point two strings that are equal
if (strObj.equals(str)) {
    System.out.println("The strings are equal");
}

// The two string references do not point to the same object
if (strObj != str) {
    System.out.println("The strings are not the same object");
}

// If we intern a string that is equal to a given literal, the result is
// a string that has the same reference as the literal.
String internedStr = strObj.intern();

if (internedStr == str) {
    System.out.println("The interned string and the literal are the same object");
}

在幕后,实习机制维护一个哈希表,其中包含仍可访问的所有内部字符串。当你在 String 上调用 intern() 时,该方法会在哈希表中查找对象:

  • 如果找到该字符串,则该值将作为实习字符串返回。
  • 否则,将字符串的副本添加到哈希表中,并将该字符串作为实习字符串返回。

可以使用 interning 来允许使用 == 比较字符串。但是,这样做有很多问题; 看到陷阱 - 实际的字符串,以便你可以使用==是一个坏主意的细节。在大多数情况下不建议使用。