比较字符串
为了比较 Strings 的相等性,你应该使用 String 对象的 equals
或 equalsIgnoreCase
方法。
例如,以下代码段将确定 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
。例如,如果你用英语比较两个单词 Taki
和 TAKI
,它们是相等的; 然而,在土耳其语中他们是不同的(土耳其语,小写的 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)
如果 foo
是 null
,则 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_ORDER
的 Comparator<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 来允许使用 ==
比较字符串。但是,这样做有很多问题; 看到陷阱 - 实际的字符串,以便你可以使用==是一个坏主意的细节。在大多数情况下不建议使用。