Почему выходные данные отличаются между JDK 1.4 и 1.5?

Я запускаю этот код с 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 ответа

Решение

Согласно этой странице, 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" всегда возвращает истину.

Вы можете попробовать с 10 и 11, чтобы проверить это.

Примечание: как уже упоминалось, Javadoc Integer#toString не говорит, будет ли возвращенная строка интернирована или нет, поэтому оба вывода в вашем вопросе одинаково действительны.

Это деталь реализации, которая не указана в JLS.

Оператор равенства ссылок == проверяет, указывают ли две переменные на один и тот же фактический объект, тогда как equals Метод проверяет, являются ли значения двух переменных "равными" каким-либо образом, который может быть определен программистом. В этом случае, похоже, что 1.4 JVM использует тот факт, что Strings являются неизменными для повторного использования одной и той же копии строки "3" когда ты звонишь valueOf а 1,5 JVM нет. Оба варианта совершенно законны, и вы не должны зависеть от какого-либо конкретного такого поведения.

От Java 5 ожидается, что string.valueof() вернет новую строку. а не intern(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

Это объясняет поведение!

Если вы используете оператор "==" для работы с строковыми литералами, то это зависит от того, присутствует ли строковое литеральное значение в "String Pool" или нет, в вашем случае переменная "str" ​​является строкой, которую JVM сначала проверяет " String Pool "если он найден, то он возвращает TRUE, иначе FALSE. Попробуйте следующий код с методом intern(), чтобы сделать строковый литерал доступным в "String Pool"

 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, это "логическая ошибка".

Другие вопросы по тегам