假设有两个Java String对象:
String str = "<my string>";
String strLower = str.toLowerCase();
对于<my string>
表达式
str.length() == strLower.length()
评估为true
?
那么,String.toLowerCase()
是否保留了String的任何值的原始字符串长度?
答案 0 :(得分:44)
令人惊讶的是,不 !!
的Java文档使用给定Locale的规则将此String中的所有字符转换为小写。案例映射基于Character类指定的Unicode标准版本。 由于大小写映射并不总是1:1 char映射,因此生成的String可能与原始String的长度不同。
示例:
package com.stackoverflow.q2357315;
import java.util.Locale;
public class Test {
public static void main(String[] args) throws Exception {
Locale.setDefault(new Locale("lt"));
String s = "\u00cc";
System.out.println(s + " (" + s.length() + ")"); // Ì (1)
s = s.toLowerCase();
System.out.println(s + " (" + s.length() + ")"); // i̇̀ (3)
}
}
答案 1 :(得分:4)
首先,我想指出,我完全同意@codaddict的(目前得分最高的)答案。
但我想做一个实验,所以这里是:
这不是一个正式的证明,但是这个代码没有到达 if
的内部(在Ubuntu上使用JDK 1.6.0 Update 16)而为我运行:
编辑:以下是一些处理语言环境的更新代码:
import java.util.Locale;
public class ToLowerTester {
public final Locale locale;
public ToLowerTester(final Locale locale) {
this.locale = locale;
}
public String findFirstStrangeTwoLetterCombination() {
char[] b = new char[2];
for (char c1 = 0; c1 < Character.MAX_VALUE; c1++) {
b[0] = c1;
for (char c2 = 0; c2 < Character.MAX_VALUE; c2++) {
b[1] = c2;
final String string = new String(b);
String lower = string.toLowerCase(locale);
if (string.length() != lower.length()) {
return string;
}
}
}
return null;
}
public static void main(final String[] args) {
Locale[] locales;
if (args.length != 0) {
locales = new Locale[args.length];
for (int i=0; i<args.length; i++) {
locales[i] = new Locale(args[i]);
}
} else {
locales = Locale.getAvailableLocales();
}
for (Locale locale : locales) {
System.out.println("Testing " + locale + "...");
String result = new ToLowerTester(locale).findFirstStrangeTwoLetterCombination();
if (result != null) {
String lower = result.toLowerCase(locale);
System.out.println("Found strange two letter combination for locale "
+ locale + ": <" + result + "> (" + result.length() + ") -> <"
+ lower + "> (" + lower.length() + ")");
}
}
}
}
使用接受的答案中提到的区域设置名称运行该代码将打印一些示例。在没有参数的情况下运行它将尝试所有可用的语言环境(并且需要一段时间!)。
它并不广泛,因为从理论上讲,可能存在行为不同的多字符字符串,但它是一个很好的第一近似值。
另请注意,以这种方式生成的许多双字符组合可能都是无效的UTF-16,因此此代码中没有任何内容爆炸的事实只能归咎于Java中非常强大的String API。
最后但并非最不重要:即使对于当前Java实现的假设是正确的,一旦Java的未来版本实现Unicode标准的未来版本,其中新标记的规则可能会引入其中的情况,这很容易改变这不再适用。
所以依赖于这仍然是一个非常糟糕的主意。
答案 2 :(得分:2)
还要记住toUpperCase()也不保留长度。示例:“straße”成为德语区域设置的“STRASSE”。因此,如果您使用区分大小写的字符串并且需要存储索引,那么您或多或少会被搞砸。