【问题标题】:Why the output is different between JDK 1.4 and 1.5?为什么 JDK 1.4 和 1.5 的输出不同?
【发布时间】:2013-08-01 20:48:06
【问题描述】:

我正在使用 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
    

【问题讨论】:

  • 使用"3".equals(str) 而非== 运算符检查字符串相等性。
  • 这与JDK之间的差异无关,而是您对String比较如何在Java中工作的理解。查看我之前评论中提供的链接
  • 要比较java中的对象相等性,你必须使用equals,如果它们引用的是同一个对象,则使用==...如果它们被实习,那么你就明白了。
  • @NarendraPathai 我认为问题是为什么 jdk 1.4 和 1.5 的输出不同。
  • @assylias 这与 1.4 和 1.5 中不同的字符串行为有关。你有什么想法?

标签: java jdk1.5 jdk1.4


【解决方案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

这解释了这种行为!

【讨论】:

  • 您正在重申操作员已经观察到的内容。问题是:为什么 1.4 和 1.5 的行为不同。
  • 因为在 java 5 中创建了新字符串而不是 intern(ed)(共享)字符串。见第一粗线!
【解决方案2】:

如果您在字符串文字的操作上使用“==”运算符,那么这取决于字符串文字值是否存在于“字符串池”中,在您的情况下,变量“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() 方法()。

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

str[3]
equals result[false]
else

使用 intern() 输出:

str[3]
equals result[true]
if

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

【讨论】:

    【解决方案3】:

    根据this pageInteger#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" 是 inned 并且 "3" == "3" 总是返回 true。

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

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

    【讨论】:

    • +1 在 Java 7 中再次不同。你不应该依赖这样的行为。
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 2021-08-29
      • 1970-01-01
      相关资源
      最近更新 更多