Confrontando Carattere, Integer e tipi simili in Java: Usa è uguale o ==?
Domanda
Ho voluto fare in modo di qualcosa in Java: Se ho un carattere o un intero o una lunga e quelli genere di cose, dovrei usare uguale o == sufficienti?
So che con le stringhe non ci sono garanzie che ci sia una sola istanza di ogni stringa univoca, ma non sono sicuro di altri tipi boxed.
La mia intuizione è quella di utilizzare eguali, ma voglio fare in modo che non sto sprecando prestazioni.
Soluzione
EDIT: Le specifiche rende alcuni garanzie per le conversioni di boxe. Dalla sezione rel="noreferrer"> href="http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7"
Se il valore p essere inscatolato è vero, falso, un byte, un char nella gamma \ U0000 a \ u007F, o un int o corto numero compreso tra -128 e 127, poi lasciare r1 e r2 essere i risultati di due qualsiasi conversioni boxe di p. E 'sempre il caso che r1 == r2.
L'implementazione può usare una piscina più grande, si badi bene.
Mi davvero evitare la scrittura di codice che si basa su quella però. Non perché potrebbe non riuscire, ma perché non è ovvio - poche persone saprà la specifica che bene. (Ho già pensato che fosse implementazione-dipendente.)
Si dovrebbe usare equals
o confrontare i valori alla base, cioè.
if (foo.equals(bar))
o
if (foo.intValue() == bar.intValue())
Si noti che anche se l'autoboxing fosse garantito da usare valori fissi, gli altri chiamanti possono sempre creare istanze separate in ogni caso.
Altri suggerimenti
Se si desidera confrontare nulla circa il valore di qualsiasi oggetto, utilizzare .equals()
.
Anche (e soprattutto) se tali oggetti sono i tipi wrapper primitive Byte, Carattere, Corto, Integer, Long, float, double e booleane.
"==
" sempre e solo a confronto l'identità di un oggetto e che è molto, molto raramente ciò che si desidera. E di fatto mai quello che vuoi con i wrapper primitivi.
Utilizzare solo ==
in uno di questi due scenari:
- tutti i valori interessati dal raffronto sono tipi primitivi (e preferibilmente non flottante numeri in virgola)
- si vuole veramente sapere se due riferimenti si riferiscono allo stesso oggetto (questo include il confronto di
enum
s, perché il valore è inevitabile che l'identità di un oggetto)
//Quick test
public class Test {
public static void main(String[] args) {
System.out.println("Are they equal? "+ (new Long(5) == new Long(5)));
}
}
Output:
"Sono uguali? 0"
Risposta:
No, non sono uguali. È necessario utilizzare .equals o confrontare i loro valori primitivi.
Se il valore p essere inscatolato è vero, falso, un byte, un char nella gamma \ U0000 a \ u007F, o un int o corto numero compreso tra -128 e 127, poi lasciare r1 e r2 essere i risultati di due qualsiasi conversioni boxe di p. E 'sempre il caso che r1 == r2.
e
Discussione
Idealmente, la boxe un dato primitivo valore p, sarebbe sempre produrre un riferimento identici. In pratica, questo potrebbe non essere possibile utilizzando esistenti tecniche di implementazione. Le regole sopra sono un compromesso pragmatico. Il clausola finale precedente richiede che certi valori comuni sempre essere inscatolati in oggetti indistinguibili. Il implementazione può memorizzare nella cache questi, pigramente o entusiasmo.
Per altri valori, questa formulazione disabilita qualsiasi ipotesi circa il identità dei valori incasellati sul parte del programmatore. Ciò consentirebbe (Ma non richiede) la condivisione di alcuni o di tutti questi riferimenti.
In questo modo, nella maggior parte dei comuni casi, il comportamento sarà il desiderato uno, senza imporre un indebito penalizzazione delle prestazioni, in particolare su piccoli dispositivi. Meno memoria limitata implementazioni potrebbe, per esempio, memorizzare nella cache tutti i personaggi e cortometraggi, come così come numeri interi e long nel gamma di -32K -. + 32K
Quindi, in alcuni casi == lavorerà, in molti altri non lo farà. Usare sempre .equals di essere al sicuro perché non si può concessionario (in genere) come sono stati ottenuti i casi.
Se la velocità è un fattore (la maggior parte .equals iniziano con un confronto ==, o almeno dovrebbero) e si può gurantee come sono stati assegnati e si inseriscono negli intervalli di cui sopra, allora == è sicuro.
Alcuni VM può aumentare quelle dimensioni, ma è più sicuro di assumere la dimensione più piccola, come specificato dalle specifiche langauge che fare affidamento su un particolare comportamento VM, a meno che davvero davvero davvero bisogno.
Le implementazioni degli Equals (Object o) Metodo quasi iniziano sempre con
if(this == o) return true;
in modo da utilizzare equals
anche se ==
è vero è in realtà non molto di un calo di prestazioni.
mi raccomando sempre * con il metodo equals
sugli oggetti.
* naturalmente ci sono pochissime volte in cui non si deve prendere questo Consiglio.
La risposta generale è non , non si è garantito che per lo stesso valore numerico, gli oggetti lunghi si ottiene sono le stesse (anche se si limita a voi stessi di utilizzare Long.valueOf ()).
Tuttavia, è possibile che si otterrebbe un miglioramento delle prestazioni in primo luogo cercando di verificare l'uguaglianza dei riferimenti (utilizzando ==) e pari poi, se fallito, che provano (). Tutto dipende dai costi comparati del test == aggiuntivo e la chiamata di metodo ... La vostra situazione potrebbe essere diversa, ma vale la pena provare un semplice loop test per vedere quale sia il migliore.
Vale la pena notare che i valori di auto-scatola sarà usi oggetto nel pool se sono disponibili. Questo è il motivo per cui (intero) 0 == (intero) 0 ma (intero) 128! = (Integer) 128 per Java 6u13
Mi piace vedere il risultato visivo:
public static void main(String[] args)
{
Integer a = 126; //no boxed up conversion, new object ref
Integer b = 126; //no boxed up conversion, re-use memory address
System.out.println("Are they equal? " + (a == b)); // true
Integer a1 = 140; //boxed up conversion, new object
Integer b1 = 140; //boxed up conversion, new object
System.out.println("Are they equal? " + (a1 == b1)); // false
System.out.println("Are they equal? " + (new Long(5) == new Long(5))); // false
}
==
confronta il riferimento all'oggetto mentre equals(Object obj)
confronto per l'uguaglianza oggetto. Se non ci può mai essere più di un'istanza di un uguale oggetto esistente , allora si deve uso equals
per confronto di uguaglianza.
Esempi:
Integer i1 = new Integer(12345);
Integer i2 = new Integer(12345);
sono istanze di oggetti diversi, ma sono uguali in base alla parità di numero intero, quindi è necessario utilizzare equals(Object obj)
public enum Gender {
MALE, FEMALE;
}
In questo caso ci sarà una sola istanza di FEMALE
esistenti in modo ==
è sicuro da usare.