String.contains(String) 或 String.indexOf(String) - 建议
"abc".contains("Z"); // false - correct
"zzzz".contains("Z"); // false - correct
"Z".contains("Z"); // true - correct
"?and?".contains("?"); // true - correct
"?and?".contains("?"); // false - correct
"?and?".indexOf("?"); // 0 - correct
"?and?".indexOf("?"); // -1 - correct
String.indexOf(int) 并仔细考虑 String.indexOf(char) 与 char 到 int 加宽
"?and?".indexOf("?".charAt(0)); // 0 though incorrect usage has correct output due to portion of correct data
"?and?".indexOf("?".charAt(0)); // 0 -- incorrect usage and ambiguous result
"?and?".indexOf("?".codePointAt(0)); // -1 -- correct usage and correct output
Java 世界中关于字符的讨论是模棱两可的
char 或Character 的值是否可以视为单个字符?
否。在 unicode 字符的上下文中,char 或 Character 有时可以是 part of a single character,在逻辑上不应视为 a complete single character。
如果不是,什么应该被视为单个字符(逻辑上)?
任何支持 Unicode 字符的字符编码的系统都应将 unicode 的代码点视为单个字符。
因此,Java 应该非常清晰和响亮地做到这一点,而不是向用户公开过多的内部实现细节。
String 类不擅长抽象(尽管它需要大量令人困惑的understanding of its encapsulations to understand the abstraction ???,因此需要anti-pattern)。
它与一般的char 用法有何不同?
char 只能映射到基本多语言平面中的一个字符。
只有codePoint - int 可以覆盖整个Unicode 字符范围。
为什么会有这种差异?
char 在内部被视为 16-bit 无符号值,并且无法使用仅使用 2-bytes 的 UTF-16 内部表示来表示所有 unicode 字符。有时,16-bit 范围内的值必须与另一个 16-bit 值组合才能正确定义字符。
不用太冗长,indexOf、charAt、length 等方法的用法应该更明确。真诚地希望 Java 能够添加具有明确定义抽象的新 UnicodeString 和 UnicodeCharacter 类。
喜欢contains 而不是indexOf(int) 的原因
- 实际上有许多代码流将逻辑字符视为 java 中的
char。
- 在 Unicode 上下文中,
char 是不够的
- 虽然
indexOf 接受int,char 到int 的转换掩盖了用户,用户可能会执行类似str.indexOf(someotherstr.charAt(0)) 的操作(除非用户知道确切的上下文)李>
- 因此,将所有内容都视为
CharSequence(又名String)会更好
public static void main(String[] args) {
System.out.println("?and?".indexOf("?".charAt(0))); // 0 though incorrect usage has correct output due to portion of correct data
System.out.println("?and?".indexOf("?".charAt(0))); // 0 -- incorrect usage and ambiguous result
System.out.println("?and?".indexOf("?".codePointAt(0))); // -1 -- correct usage and correct output
System.out.println("?and?".contains("?")); // true - correct
System.out.println("?and?".contains("?")); // false - correct
}
语义
-
char 可以处理大部分实际用例。仍然最好在编程环境中使用代码点以实现未来的可扩展性。
-
codepoint 应该可以处理几乎所有与编码相关的技术用例。
- 不过,Grapheme Clusters 超出了
codepoint 抽象级别的范围。
- 如果
ints太贵(翻倍),存储层可以选择char接口。除非存储成本是唯一的指标,否则最好使用codepoint。此外,最好将存储视为byte,并将语义委托给围绕存储构建的业务逻辑。
- 语义可以在多个级别进行抽象。
codepoint 应该成为最低级别的接口,其他语义可以在运行时环境中围绕codepoint 构建。