2013-08-01 12 views
11

Używam tego kodu z JDK 1.4 i 1.5 i otrzymuję inne wyniki. Dlaczego tak jest?Dlaczego dane wyjściowe różnią się w JDK 1.4 i 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"); 
} 

wyjścia:

  • na jdk 1,4

    str[3] 
    equals result[true] 
    if 
    
  • na jdk 1,5

    str[3] 
    equals result[false] 
    else 
    
+7

Równość łańcuchów jest sprawdzana za pomocą '" 3 ".equals (str)', a nie za pomocą operatora '=='. –

+0

Nie ma to nic wspólnego z różnicą między JDK, ale twoją wiedzą na temat tego, jak porównanie "String" działa w Javie. Sprawdź link podany w moim poprzednim komentarzu – MadProgrammer

+0

, aby porównać równość obiektów w java, musisz użyć 'equals', używając ==, jeśli odnoszą się do tego samego obiektu ... jeśli zostały internowane, to jest to prawda. – nachokk

Odpowiedz

11

Według this page metoda Integer#toString (który nazywany jest przez String#valueOf(int)) jest realizowany w ten sposób w 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); 
} 

To wyjaśniałoby swój wynik, ponieważ ciąg dosłowne "3" internowania i "3" == "3" zawsze zwraca true.

Możesz spróbować za pomocą 10 i 11, aby to sprawdzić.

Uwaga: jak już wspomniano, javadoc z Integer#toString nie mówi, czy zwracany ciąg będzie internowany, czy też nie, tak że oba wyniki w pytaniu są jednakowo ważne.

+2

+1 W Java 7 jest znowu inny. Nie powinieneś polegać na takich zachowaniach. –

4

to imp szczegóły dotyczące lementacji, które nie zostały określone przez JLS.

operator równości odniesienia == sprawdza, czy dwie wartości wskazują na ten sam rzeczywistego obiektu, natomiast equals Sposób kontroli w celu sprawdzenia, czy wartości dwóch zmiennych są «równy» w pewien sposób, który może być określony za pomocą programatora. W tym przypadku okazuje się, że 1.4 JVM korzysta z faktu, że String s są niezmienne, aby ponownie użyć tej samej kopii ciągu "3", gdy zadzwonisz pod numer valueOf, a 1.5 JVM nie. Obie opcje są całkowicie legalne i nie powinieneś polegać na żadnym konkretnym takim zachowaniu.

0

Jeśli używasz operatora "==" do działania literałów String, to zależy to od tego, czy wartość literału ciągu jest obecna w "String Pool", czy nie, w twojej zmiennej zmiennej "str" ​​jest ciągiem JVM najpierw sprawdza "String Pool", jeśli zostanie znaleziony, następnie zwraca TRUE else FALSE. Spróbuj następującego kodu metodą intern(), aby ciąg dosłowne dostępny na „ciąg 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"); 
} 

według dokumentacji dla metody intern(): intern() metoda przeszukuje wewnętrzną tablicę ciągów dla ciąg równy temu ciągowi. Jeśli ciąg nie znajduje się w tabeli, zostanie dodany. Odpowiedzi na ciąg zawarty w tabeli, który jest równy temu Stringowi. Ten sam obiekt łańcucha jest zawsze odpowiedziony na ciągi, które są równe.

Funkcja "==" nie jest zalecana do porównywania ciągów. użyj metody equals() lub equalsIgnoreCase()().

Próbowałem nawet w Javie 1.7 bez intern() wyjście

str[3] 
equals result[false] 
else 

z intern() wyjście dochodzi do:

str[3] 
equals result[true] 
if 

Nie jest to problemem jdk 1.4 i 1.5 jest to „logiczne błąd".

1

Z java 5 string.valueof() ma zwrócić nowy ciąg. zamiast intern (ed) (shared) string!

Rozważmy następujący przykład

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"); 

wyjście w Javie> = 5

valueOf does not return interned string 

Ale w java 4 wyjściowy jest

valueOf return interned string 

To wyjaśnia zachowanie!

+0

Powtarzasz to, co już zaobserwował op. Pytanie brzmi: dlaczego 1.4 i 1.5 zachowują się inaczej. – assylias

+0

Ponieważ w języku java tworzony jest 5 nowy ciąg znaków, a nie intern (ed) (udostępniony) ciąg znaków. Zobacz pierwszą pogrubioną linię! –

Powiązane problemy