11

我正在使用 JDK 1.4 和 1.5 运行此代码并得到不同的结果。为什么会这样?

String str = "";
int test = 3;

str = String.valueOf(test);
System.out.println("str[" + str + "]\nequals result[" + (str == "3") + "]");

if (str == "3") {
    System.out.println("if");
} else {
    System.out.println("else");
}

输出:

  • 在 jdk 1.4 上

    str[3]
    equals result[true]
    if
    
  • 在 jdk 1.5 上

    str[3]
    equals result[false]
    else
    
4

4 回答 4

11

根据this page,该Integer#toString方法(由 调用String#valueOf(int))在1.4中实现如下:

public static String toString(int i) {  
    switch(i) {  
        case Integer.MIN_VALUE: return "-2147483648";  
        case -3: return "-3";  
        case -2: return "-2";  
        case -1: return "-1";  
        case 0: return "0";  
        case 1: return "1";  
        case 2: return "2";  
        case 3: return "3";  
        case 4: return "4";  
        case 5: return "5";  
        case 6: return "6";  
        case 7: return "7";  
        case 8: return "8";  
        case 9: return "9";  
        case 10: return "10";  
    }  
    char[] buf = (char[])(perThreadBuffer.get());  
    int charPos = getChars(i, buf);  
    return new String(buf, charPos, 12 - charPos);  
}

这可以解释你的结果,因为字符串文字"3"是实习的,并且"3" == "3"总是返回 true。

您可以尝试使用 10 和 11 来验证这一点。

注意:如前所述,javadocInteger#toString没有说明返回的字符串是否会被实习,因此您问题中的两个输出都同样有效。

于 2013-08-01T05:30:48.327 回答
4

这是 JLS 未指定的实现细节。

引用相等运算符==检查两个变量是否指向同一个实际对象,而该equals方法检查两个变量的值是否以某种可能由程序员确定的方式“相等”。在这种情况下,1.4 JVM 似乎利用了 s 是不可变的这一事实,以便在您调用时String重用字符串的相同副本,而 1.5 JVM 则不是。这两种选择都是完全合法的,您不应依赖任何特定的此类行为。"3"valueOf

于 2013-08-01T05:18:17.003 回答
1

从 java 5 string.valueof() 预计会返回新字符串。而不是实习生(ed)(共享)字符串!

考虑以下示例

    int test = 3;
    String str = String.valueOf(test);
    String str2 = String.valueOf(test);

    if(str == str2)
        System.out.println("valueOf return interned string");
    else
        System.out.println("valueOf does not return interned string");

java中的输出> = 5

valueOf does not return interned string

但在 java 4 中的输出是

valueOf return interned string

这解释了这种行为!

于 2013-08-01T06:25:38.300 回答
0

如果您在字符串文字的操作上使用“==”运算符,那么它取决于字符串文字值是否存在于“字符串池”中,在您的情况下,变量“str”是一个字符串 JVM 首先检查“字符串池”如果找到,则返回 TRUE,否则返回 FALSE。使用 intern() 方法尝试以下代码,以使字符串文字在“字符串池”上可用

 String str = "";
 int test = 3;

 str = String.valueOf(test).intern();

 System.out.println("str[" + str + "]\nequals result[" + (str == "3") + "]");

 if (str == "3") {
     System.out.println("if");
 } else {
     System.out.println("else");
 }

根据 intern() 方法的文档:intern() 方法在字符串的内部表中搜索与此字符串相等的字符串。如果字符串不在表中,则将其添加。回答表中包含的与此字符串相等的字符串。对于相等的字符串,总是会回答相同的字符串对象。

那么字符串比较不推荐使用“==”操作。使用equals() 或equalsIgnoreCase() 方法()。

我什至在没有intern() 的java 1.7 中尝试过,输出是

str[3]
equals result[false]
else

使用intern() 的输出为:

str[3]
equals result[true]
if

这不是 jdk 1.4 和 1.5 的问题,这是一个“逻辑错误”。

于 2013-08-01T05:44:38.383 回答