【问题标题】:equalsIgnoreCase doesn't conform to javadoc?equalsIgnoreCase 不符合 javadoc?
【发布时间】:2014-02-03 04:57:38
【问题描述】:

String.equalsIgnoreCase 的 javadoc 说:

如果两个字符串的长度相同,并且两个字符串中的对应字符相等,忽略大小写,则认为两个字符串相等。 如果以下至少一项为真,则两个字符 c1 和 c2 被认为是相同的忽略大小写:

这两个字符相同(通过 == 运算符比较)

对每个字符应用 Character.toUpperCase(char) 方法会产生相同的结果

对每个字符应用 Character.toLowerCase(char) 方法会产生相同的结果

那么谁能解释一下?

public class Test
{
    private static void testChars(char ch1, char ch2) {
        boolean b1 = (ch1 == ch2 ||
                   Character.toLowerCase(ch1) == Character.toLowerCase(ch2) ||
                   Character.toUpperCase(ch1) == Character.toUpperCase(ch2));
        System.out.println("Characters match: " + b1);

        String s1 = Character.toString(ch1);
        String s2 = Character.toString(ch2);
        boolean b2 = s1.equalsIgnoreCase(s2);
        System.out.println("equalsIgnoreCase returns: " + b2);
    }

    public static void main(String args[]) {
        testChars((char)0x0130, (char)0x0131);
        testChars((char)0x03d1, (char)0x03f4);
    }
}

输出:

Characters match: false
equalsIgnoreCase returns: true
Characters match: false
equalsIgnoreCase returns: true

【问题讨论】:

  • 您使用哪个 Java 版本进行编译/运行?这些是格鲁吉亚字母吗?
  • 看到这个,我想这有关系:mail.openjdk.java.net/pipermail/i18n-dev/2011-August.txt
  • 这是土耳其字母的已知问题,请看这里:w3.org/International/wiki/Case_folding, 'Turkish i/I etc.'
  • JRE 7(java -version 表示1.7.0_03)。不,他们不是格鲁吉亚人。一个是土耳其无点的“i”事物,另一个与希腊 theta 的替代形式有关。
  • Java 8 仍然有 bug,文档也没有修复。

标签: java


【解决方案1】:

这些字符的大小写定义可能是特定于语言环境的。来自Character.toLowerCase() 的 JavaDoc:

一般情况下,应该使用 String.toLowerCase() 将字符映射到 小写。字符串大小写映射方法有几个好处 字符大小写映射方法。字符串大小写映射方法可以 执行区域敏感映射、上下文敏感映射和 1:M 字符映射,而字符大小写映射方法不能。

如果您查看String.toLowerCase() 方法,您会发现它也被覆盖以接受Locale 对象。这将执行特定于语言环境的大小写转换。

编辑:我想明确一点,是的,String.equalsIgnoreCase() 的 JavaDoc 说明了它所说的内容,但它是错误的。它不可能在所有情况下都是正确的,例如对于具有代理项的字符当然不是正确的,对于语言环境定义大写/小写的字符也是如此。

【讨论】:

  • (1) 我没有使用String.toLowerCase(); (2) 由于文档说String.toLowerCase() 对语言环境敏感,但Character.toLowerCase() 不是,我不明白你的第一句话怎么可能是正确的; (3)即使定义有缺陷,我仍然希望方法按照定义起作用,但似乎不是。
  • 我的观点是字符串转换是区域感知的,而字符转换不是。就像我的编辑说的那样,JavaDoc 被证明是不正确的。
【解决方案2】:

我在String.java 中找到了这个(这个 sn-p 也在 peter.petrov 链接到的文档中):

        if (ignoreCase) {
            // If characters don't match but case may be ignored,
            // try converting both characters to uppercase.
            // If the results match, then the comparison scan should
            // continue.
            char u1 = Character.toUpperCase(c1);
            char u2 = Character.toUpperCase(c2);
            if (u1 == u2) {
                continue;
            }
            // Unfortunately, conversion to uppercase does not work properly
            // for the Georgian alphabet, which has strange rules about case
            // conversion.  So we need to make one last check before
            // exiting.
            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                continue;
            }
        }

它被equalsIgnoreCase使用。有趣的是,如果它按照javadoc所说的那样,底部的行应该是

            if (Character.toLowerCase(c1) == Character.toLowerCase(c2)) {

使用c1c2 代替u1u2。这会影响这两种情况的结果。我们都同意 javadoc 是“错误的”,因为它并没有真正反映案例折叠应该如何工作。但是上面的逻辑并没有更好地处理正确的大小写折叠,而且它不符合文档。

【讨论】:

    猜你喜欢
    • 2012-07-21
    • 2015-10-28
    • 1970-01-01
    • 2021-09-07
    • 2016-04-06
    • 1970-01-01
    • 2012-07-17
    • 2013-04-28
    • 1970-01-01
    相关资源
    最近更新 更多