Domanda su = = operatore in java


public class Demo {  

    public static void main(String[] args) {

        String s1 = "Hello";
        String s2 = "Hello";
        System.out.println("s1 == s2 " + (s1 == s2));

        String s5 = "Hel" + "lo";
        String s6 = "He" + "llo";
        System.out.println("s5 == s6 " + (s5 == s6));

        String s7 = "He";
        String s8 = "Hello";
        s7 = s7.concat("llo");
        System.out.println("s7 == s8 " + (s7 == s8));

        String s10 = "He";
        s10 = s10 + "llo";
        System.out.println("s1 == s10 "+(s1 == s10));
    }
}

Nel codice precedente s7 = = s8 e s1 = = s10 danno false. Qualcuno può per favore spiegarmi, cosa è effettivamente successo qui in s7 = s7.concat ("llo"); e s10 = s10 + "llo"; Capisco == l'operatore controlla il riferimento e equal () controlla il contenuto dell'oggetto. Ma ho bisogno di sapere perché i modelli di bit delle variabili di riferimento s7 e s10 sono diversi da s8 e s1. Se queste cose sono correlate con le stringhe generate dal tempo di compilazione e le stringhe generate dal tempo di esecuzione allora come posso identificare se lo è tempo di compilazione o stringa di tempo di esecuzione?

Author: halfdan, 2010-09-26

7 answers

Il motivo per cui ciò sta accadendo è perché Java sta ottimizzando nel compilatore. Quando vede che stai assegnando la stringa letterale "Hello" a s1, usa lo stesso "Ciao" per s2, poiché tutte le operazioni di stringa Java non sono distruttive (ad esempio restituiscono un clone piuttosto che modificare l'originale), quindi è una cosa sicura da fare.

La stessa cosa vale per "Hel" + "lo" vs "He" + "llo"; è abbastanza intelligente da capire che sono la stessa cosa.

Gli altri sono abbastanza complessi da non poter ottimizzare loro, e quindi si finisce con oggetti separati.

 11
Author: Clint Tseng, 2010-09-26 19:34:55

== non controlla i modelli di bit, confronterà l'indirizzo di memoria per gli oggetti. Solo lo stesso oggetto ha lo stesso indirizzo di memoria.

 4
Author: Alexander Sagen, 2010-09-26 19:36:47

La risposta di Clint va bene, ma la espanderò ulteriormente e spiegherò a livello di compilatore.

Come sapete, s1 e s2 finiranno per essere riferimenti alla stessa istanza di stringa, "Hello".

Per s5 e s6, il compilatore vede espressioni costanti. Cioè, vede un'operazione tra due costanti (i letterali di stringa). Il compilatore sa come aggiungere stringhe e quale sarebbe il risultato. Poiché i valori sono noti immediatamente in fase di compilazione, fa il aggiunta per te, risultante nella stringa letterale "Hello". Di conseguenza, ha lo stesso valore di s1 e s2, quindi ognuno farà riferimento alla stessa istanza.

s7 non può essere semplificato allo stesso modo. s7 inizia inizialmente con "He" ovviamente. La differenza qui è che s7 = s7.concat("llo"); come riassegnare s7 al risultato di una chiamata di funzione. Questo non potrebbe essere semplificato così com'è. Per quanto riguarda il compilatore Java, i risultati di tutte le chiamate di funzione non sono noti in fase di compilazione. Poiché non conosce il valore risultante, non può essere semplificato e viene lasciato così com'è. La chiamata risultante restituisce una nuova istanza di una stringa "Hello" che non è la stessa istanza dell'istanza in fase di compilazione (che s8 condivide).

s10 non può essere semplificato allo stesso modo pure. s10 inizia inizialmente con "He" ovviamente. Quindi viene riassegnato s10 = s10 + "llo"; Questo non può essere semplificato. Perché si potrebbe chiedere? Bene s10 è un'espressione variabile non finale. Significato tecnicamente, il il compilatore non conosce il suo valore perché non è una costante. Se s10 è stato dichiarato un final String, allora questo potrebbe essere costante piegato (quando assegnato a una variabile diversa).

Quindi considera questa versione del tuo codice di test:

public static void main(String[] args)
{
    String s1 = "Hello";
    String s2 = "Hello";
    System.out.println("1: s1 == s2 " + (s1 == s2));    // 1

    String s3 = "Hel" + "lo";
    String s4 = "Hel".concat("lo");
    System.out.println("2: s1 == s3 " + (s1 == s3));    // 2
    System.out.println("3: s1 == s4 " + (s1 == s4));    // 3

    String he = "He";
    String s5 = he + "llo";
    String s6 = he.concat("llo");
    System.out.println("4: s1 == s5 " + (s1 == s5));    // 4
    System.out.println("5: s1 == s6 " + (s1 == s6));    // 5

    final String fhe = "He";
    String s7 = fhe + "llo";
    String s8 = fhe.concat("llo");
    System.out.println("6: s1 == s7 " + (s1 == s7));    // 6
    System.out.println("7: s1 == s8 " + (s1 == s8));    // 7
}

Riesci a capire quali linee sono vere?

falso, falso, falso, falso, falso, falso
Ci si potrebbe chiedere perché il 3 e 7 non sono vere. Risposta breve, il compilatore Java non è stato programmato
essere abbastanza intelligente da riconoscere la chiamata concat (), quindi viene trattata come una normale chiamata di funzione.

 4
Author: Jeff Mercado, 2010-09-27 05:35:20

L'operatore equals verifica se i riferimenti sono gli stessi (cioè puntano allo stesso oggetto), non se i valori dei riferimenti sono gli stessi. Se è necessario verificare se una stringa è uguale a un'altra, è necessario utilizzare il built-in .metodo uguale. Questo farà un confronto del valore dell'oggetto. ad esempio

final String expectedValue = "Foo";
final String actualValue = "F" + "oo";
if (expectedValue.equals(actualValue)) {
  // This will trigger where == would not
}

Inoltre, per motivi di sicurezza, se si confrontano due stringhe e una è una costante, di solito è meglio invocare equals sulla costante, cioè

String myValue = getMyValue;
boolean theSame = "Some value".equals(myValue);

Anziché

String myValue = getMyValue;
boolean theSame = myValue.equals("Some Value");

Il la ragione è che il secondo modulo rischia un'eccezione di puntatore nullo che può essere evitata invocando equals () sulla stringa costante che è garantita.

 0
Author: locka, 2010-09-26 19:38:07

Non è possibile fare alcuna ipotesi sugli oggetti string.

Una VM potrebbe lavorare sodo per assicurarsi che non esistano due oggetti string contenenti esattamente lo stesso array di caratteri allo stesso tempo, mentre altre VM consentirebbero duplicati.

 0
Author: Barthelemy, 2010-09-26 19:38:23

L'operatore == controlla solo se due oggetti hanno lo stesso indirizzo (puntatore). Solo per tipi primitivi che non sono referenece (come int, char, ecc.) confronta il valore.

È necessario utilizzare qualcosa come s1.equals(s2) per confrontare il contenuto di due stringhe.

 0
Author: erjiang, 2010-09-26 19:39:31

Nell'esempio che hai fornito questo è ciò che sta accadendo:

String s7 = “He”;    //s7 is an object referencing a part of memory holding “He”
String s8 = “Hello”;   //s8 is an object referencing a part of memory holding “Hello”
s7 = s7.concat(“llo”); //s7.concat(“llo”) created a new object in memory that contains “Hello” and s7 now references this now object 

(s7==s8)             //checks if the equality of the object reference and this is false since they reference different memory addresses.

(s7.equals(s8))         //this will compare s7 and s8 however way the String class compares two String objects. 
 0
Author: Vijay Selvaraj, 2010-09-26 19:59:44