java - 为什么 String.endsWith 和 String.startsWith 不一致?

标签 java string character-encoding locale

<分区>

我有下面的测试用例,只有第一个断言通过了。为什么?

@Test
public void test() {
    String i1 = "i";
    String i2 = "İ".toLowerCase();

    System.out.println((int)i1.charAt(0)); // 105
    System.out.println((int)i2.charAt(0)); // 105

    assertTrue(i2.startsWith(i1));

    assertTrue(i2.endsWith(i1));
    assertTrue(i1.endsWith(i2));
    assertTrue(i1.startsWith(i2));
}

回复后更新

我正在尝试以不区分大小写的方式使用 startsWithendsWith,这样,下面的表达式应该返回 true。

"ALİ".toLowerCase().endsWith("i");

我猜 C# 是不同的和 Java .

最佳答案

发生这种情况是因为小写 ©(“拉丁大写字母 i with dot above") 转换为两个字符:"拉丁小写字母 i"和 "combining dot above"。

这解释了为什么它以 i 开头,但不以 i 结尾(而是以组合变音符号结尾)。

在土耳其语言环境中,根据土耳其语言学规则,小写字母 İ 会简单地变成“拉丁文小写字母 i”,因此您的代码可以正常工作。

这里有一个测试程序可以帮助弄清楚发生了什么:

class Test {
  public static void main(String[] args) {
    char[] foo = args[0].toLowerCase().toCharArray();
    System.out.print("Lowercase " + args[0] + " has " + foo.length + " chars: ");
    for(int i=0; i<foo.length; i++) System.out.print("0x" + Integer.toString((int)foo[i], 16) + " ");
    System.out.println();
  }
}

这是我们在配置为英语的系统上运行它时得到的结果:

$ LC_ALL=en_US.utf8 java Test "İ"
Lowercase İ has 2 chars: 0x69 0x307

这是我们在为土耳其语配置的系统上运行它时得到的结果:

$ LC_ALL=tr_TR.utf8 java Test "İ"
Lowercase İ has 1 chars: 0x69

这甚至是 API 文档为 String.toLowerCase(Locale) 使用的具体示例,这是您可以用来获取特定语言环境(而不是系统默认语言环境)中的小写版本的方法。

关于java - 为什么 String.endsWith 和 String.startsWith 不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45514930/

相关文章:

java - 为什么在方法上打开调用层次结构不起作用

java - 将 bean 添加到 Autowiring 列表

java - java中字符串到字节

python - 基于 Python/MySQL 的管道中的字符编码问题

Java FX "mass"处理按钮

java - Jboss接缝: Enabling Debug page on WebLogic 10. 3.2(11g)

java - 如何将每个句子的第一个字母转换为大写并将所有其他字母转换为小写?

c++ - 如何在C++中的Enter处停止接受字符串

java - 如何检测 Java 字符串中的日语文本?

java - 用于打开 Ms-Dos 编辑器并保存文件的批处理文件