Android replaceAll和字符串比较==

时间:2014-04-04 01:20:36

标签: java android string

在审核android源代码时,我发现了一个使用==而不是equals()的字符串比较错误。但是,该应用程序运行得令人惊讶!

经过一些测试,我发现replaceAll()方法隐藏了这个bug。

String description = " ";
description = description.trim();
Result1.setText(description + " == " + "" + ": " + (description == ""));

按照我的预期打印“==:false”。然而,

String description = " ";
description = description.trim().replaceAll("\\s+|\\r+|\\n+", " ");
Result1.setText(description + " == " + "" + ": " + (description == ""));

打印“==:true”! (Android 4.4.2,API 19)

我在桌面上运行相同的代码(javac 1.6.0_45)并按照我的预期打印“==:false”。

它是Android中的错误还是预期的行为?

1 个答案:

答案 0 :(得分:1)

不,它不是一个错误 - 它只是一个泄漏的实施细节。

java编译器创建代码中使用的字符串池。空字符串肯定是其中之一。无论何时在编译时将变量设置为空字符串,它都将指向空字符串的同一实例。所以

String a = "";
String b = "";

if (a == b) {
   //this will always be true in practice, although I don't know if it's guaranteed
}

现在假设trim()和replaceAll()的实现方式不同:

String trim() {
    byte[] b = getBytes();
    ...
    return new String(b, 0, len);
}

String replaceAll (String needle, String replacement) {
    String result = "";
    int pos = 0;
    while (indexOf(needle, pos) != -1) {
        ...
        result = result + replacement;
        pos = ...;
    }
    return result;
}

因为trim()调用了一个String构造函数,所以它必然会创建一个新的String。但是replaceAll以一个空字符串开始并构建。它开头的空字符串与源代码中所有其他空字符串的空字符串相同。

这些是虚假的实施 - 它只是一个假设,它是如何运作的。它与观察到的数据相匹配,但我没有读取Android代码。不过,它表明类似功能的不同实现可能会导致您看到的效果。

换句话说,它不是一个错误,但它不是你想要依赖的行为。如果你想依赖两个字符串.equal()也是==,你可以使用String.intern()。