Примите два Строковых объекта Java:
String str = "<my string>";
String strLower = str.toLowerCase();
Это затем верно это для каждого значения <my string>
выражение
str.length() == strLower.length()
оценивает к true
?
Так, делает String.toLowerCase()
сохранить длину исходной строки для какого-либо значения Строки?
Удивительно, но это , а не !!
Из документации Java вLowerCase
Преобразует все символы в этой строке в нижний регистр, используя правила данной локали. Отображение регистра основано на версии Unicode Standard, указанной классом Character. Поскольку сопоставления регистра не всегда являются отображениями символов 1: 1, длина результирующей строки может отличаться от длины исходной строки.
Пример:
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)
}
}
Прежде всего, я хотел бы отметить, что я полностью согласен с (в настоящее время самым высоким) ответом @codaddict.
Но я хотел провести эксперимент, так что вот он:
Это не формальное доказательство, но этот код работал для меня, так и не достигнув внутренней части if
(с использованием JDK 1.6. 0 Обновление 16 в Ubuntu):
Изменить: Вот обновленный код, который также обрабатывает локали:
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, поэтому тот факт, что ничего не взрывается в этом коде, можно объяснить только очень надежным String API в Java.
И последнее, но не менее важное: даже если предположение верно для текущей реализации Java, это может легко измениться, как только будущие версии Java реализуют будущие версии стандарта Unicode, в которых правила для новых символов могут создавать ситуации, когда это больше не так.
Так что полагаться на это все еще довольно плохая идея.