Java 为什么String.endsWith和String.startWith不一致?
我有下面的测试用例,只有第一个断言通过。为什么?Java 为什么String.endsWith和String.startWith不一致?,java,string,character-encoding,locale,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));
@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));
}
回复后更新
我试图以不区分大小写的方式使用startsWith
和endsWith
,这样,下面的表达式应该返回true
"ALİ".toLowerCase().endsWith("i");
我猜和是不同的。
İ
是Unicode字符,是一个长度为1的Java字符串
“İ”.toLowerCase()
返回一个长度为2的Java字符串:
- Unicode字符(普通的
)i
- Unicode字符
这是因为没有像“
”上面有点的拉丁文小写字母I”
这样的字符。它在Unicode中不存在。执行toLowerCase()
函数后,字符串长度为2而不是1;该字符的小写版本由两个字符表示:
000> "İ".length()
===> 1
000> "İ".toLowerCase().length()
===> 2
其小写表示形式中的第一个字符是小写拉丁语i
,而第二个字符是变音符号:
000> "İ".toLowerCase().charAt(0)
===> i
000> "İ".toLowerCase().charAt(1)
===> ̇
因此,小写字符串确实以“
i
”开头,但不以它结尾。之所以会出现这种情况,是因为小写的İ
(“拉丁大写字母
在英语语言环境中,i和上面的点)变成两个字符:“拉丁文小写字母i
”和“合并上面的点”
这解释了为什么它以i
开头,而不是以i
结尾(它以组合变音符号结尾)
在土耳其语言环境中,小写code>根据土耳其语言学规则,简单地变成“拉丁小写字母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();
}
}
以下是我们在为Turkish配置的系统上运行时得到的结果:
$ LC_ALL=tr_TR.utf8 java Test "İ"
Lowercase İ has 1 chars: 0x69
这甚至是API文档使用的特定示例,您可以使用该方法获取特定区域设置中的小写版本,而不是系统默认区域设置。您的测试失败,因为您使用了错误的方法
String i2=“İ”
是i的土耳其语大写形式,如果您不提供转换的区域设置,则该方法将失败
使用区域设置可能会有所帮助:)
输出将是
105
105
真的
真的
真的
真的
你能不能把你的问题改一下,这样你就不会做toLowerCase()
?什么是字符toLowerCase()
outputs?请查看我的更新println
sNow尝试打印i1.length()
和i2.length()
。确定长度不同:)我再次更新了我的问题。不接受字符串作为参数,也不返回布尔值,因此无法计算为true。如果我不知道区域设置,该怎么办?
$ LC_ALL=tr_TR.utf8 java Test "İ"
Lowercase İ has 1 chars: 0x69
public static void main(String[] args) {
String i1 = "i";
String i2 = "İ".toLowerCase(Locale.forLanguageTag("tr-TR"));
System.out.println((int)i1.charAt(0)); // 105
System.out.println((int)i2.charAt(0)); // 105
System.out.println(i2.startsWith(i1));
System.out.println(i2.endsWith(i1));
System.out.println(i1.endsWith(i2));
System.out.println(i1.startsWith(i2));
}