关于Android在土耳其语言下equals和toLowerCase失效问题

1,748 阅读1分钟
原文链接: www.jianshu.com

请看下面的代码:

"i".equals(xx.toLowerCase());

其中,xx 是服务端返回的字段,字段值是“I”(大写的i)。

看到这样的代码,我们可能不假思索的认为肯定是 true 啊,不可能有其他值。

真的是这样吗?天哥还真遇到了为 false 的情况。

经测试和验证发现,Android/Java 在默认 Locale 被设置成土耳其语的情况下,使用 toLowerCase会导致“I”变成“ı”,在源码注释中也有说明。

/**
     * Converts all of the characters in this {@code String} to lower
     * case using the rules of the default locale. This is equivalent to calling
     * {@code toLowerCase(Locale.getDefault())}.
     * <p>
     * <b>Note:</b> This method is locale sensitive, and may produce unexpected
     * results if used for strings that are intended to be interpreted locale
     * independently.
     * Examples are programming language identifiers, protocol keys, and HTML
     * tags.
     * For instance, {@code "TITLE".toLowerCase()} in a Turkish locale
     * returns {@code "t\u005Cu0131tle"}, where '\u005Cu0131' is the
     * LATIN SMALL LETTER DOTLESS I character.
     * To obtain correct results for locale insensitive strings, use
     * {@code toLowerCase(Locale.ROOT)}.
     * <p>
     * @return  the {@code String}, converted to lowercase.
     * @see     java.lang.String#toLowerCase(Locale)
     */
    public String toLowerCase() {
        return toLowerCase(Locale.getDefault());
    }

所以我们文章开始的那段代码通常情况下都是正确的,因为我们几乎不会搞个土耳其语,也就忽视了这个问题。碰巧,天哥做国际化的,遇到了。

I 只是目前遇到的,是否还有其他字母在其他语言中有特殊转换,我们也不清楚楚。所以,为了保证 toLowerCase 的正确性,我们有两个解决方案:

1、使用 toLowerCase(Locale) 带 locale 参数的方法, Locale 设定为(en_US)。

"i".equals(xx.toLowerCase(Locale.US));

也就是把语义设置在英文环境下,就可以避免这个问题。

2、使用系统 equalsIgnoreCase 方法来做比较,也不会引入这个问题。

"i". equalsIgnoreCase(xx);