Java的toLowerCase()是否保留原始字符串长度?

假设有两个Java String对象:

String str = ""; String strLower = str.toLowerCase(); 

对于的每个值,表达式是否正确呢?

 str.length() == strLower.length() 

评估为true

那么, String.toLowerCase()保留String的任何值的原始字符串长度?

令人惊讶的是它没有 !!

从Java文档到toLowerCase

使用给定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) } } 

首先,我想指出,我完全同意@codaddict的(目前得分最高的)答案。

但是我想做一个实验,所以这里是:

这不是一个正式的certificate,但这个代码为我运行而没有到达if的内部(在Ubuntu上使用JDK 1.6.0 Update 16):

编辑:这里有一些处理Locales的更新代码:

 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 (" + result.length() + ") -> <" + lower + "> (" + lower.length() + ")"); } } } } 

使用接受的答案中提到的区域设置名称运行该代码将打印一些示例。 在没有参数的情况下运行它将尝试所有可用的语言环境(并且需要一段时间!)。

它并不广泛,因为理论上可能存在行为不同的多字符字符串,但它是一个很好的第一近似值。

另请注意,以这种方式生成的许多双字符组合可能都是无效的UTF-16,因此在此代码中没有任何爆炸的事实只能归咎于Java中非常强大的String API。

最后但并非最不重要的是:即使对于当前Java实现的假设是正确的,一旦Java的未来版本实现Unicode标准的未来版本,其中新标记的规则可能会引入不再存在的情况,这很容易改变是的。

所以依赖于这仍然是一个非常糟糕的主意。

还要记住toUpperCase()也不保留长度。 示例:“straße”成为德语区域设置的“STRASSE”。 因此,如果您使用区分大小写的字符串并且需要存储某些内容的索引,那么您或多或少会被搞砸。