Volevo chiarire se ho capito bene:
==
è un confronto di riferimento, ovvero entrambi gli oggetti puntano alla stessa posizione di memoria.equals()
valuta il confronto dei valori negli oggetti
.equals()
che sia significativamente equivalente
Volevo chiarire se ho capito bene:
==
è un confronto di riferimento, ovvero entrambi gli oggetti puntano alla stessa posizione di memoria.equals()
valuta il confronto dei valori negli oggetti.equals()
che sia significativamente equivalente
Risposte:
In generale, la risposta alla tua domanda è "sì", ma ...
.equals(...)
confronterà solo ciò che è scritto per confrontare, né più né meno.equals(Object o)
metodo della classe genitore più vicina che ha ignorato questo metodo.Object#equals(Object o)
metodo. Per l'API Object è lo stesso di ==
; cioè restituisce vero se e solo se entrambe le variabili si riferiscono allo stesso oggetto, se i loro riferimenti sono uguali. Quindi testerai l'uguaglianza degli oggetti e non l' uguaglianza funzionale .hashCode
se esegui l'override equals
per non "rompere il contratto". Come per l'API, il risultato restituito dal hashCode()
metodo per due oggetti deve essere lo stesso se i loro equals
metodi mostrano che sono equivalenti. Il contrario non è necessariamente vero.==
verifica il riferimento alla memoria, perché sto ottenendo questo strano comportamento in [this] [1] [1]: docs.google.com/document/d/… Mi aspettavo che l'output fosse vero. posso cancellare le mie confusioni
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
<br/> Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
( docs.oracle.com/javase/7/docs/api/java/lang/… )
Rispetto alla classe String:
Il metodo equals () confronta il "valore" all'interno delle istanze String (sull'heap) indipendentemente dal fatto che i due riferimenti a oggetti facciano riferimento alla stessa istanza String o meno. Se due riferimenti a oggetti di tipo String fanno riferimento alla stessa istanza di String, allora fantastico! Se i due riferimenti agli oggetti si riferiscono a due diverse istanze di String .. non fa differenza. È il "valore" (ovvero: il contenuto dell'array di caratteri) all'interno di ogni istanza String che viene confrontata.
D'altra parte, l' operatore "==" confronta il valore di due riferimenti a oggetto per vedere se si riferiscono alla stessa istanza String . Se il valore di entrambi i riferimenti all'oggetto "fa riferimento" alla stessa istanza String, il risultato dell'espressione booleana sarebbe "vero" .. duh. Se, d'altra parte, il valore di entrambi i riferimenti a oggetto "fa riferimento a" diverse istanze di String (anche se entrambe le istanze di String hanno "valori" identici, ovvero il contenuto degli array di caratteri di ciascuna istanza di String è lo stesso) il il risultato dell'espressione booleana sarebbe "falso".
Come con qualsiasi spiegazione, lascia che affondi.
Spero che questo chiarisca un po 'le cose.
String
s, anche il ==
riferimento è uguale, sì, ma di solito funziona (come in due String
s con lo stesso contenuto sarà di solito l' uno ==
con l'altro), a causa di come Java gestisce String
s. Non sempre, ed è certamente una cattiva pratica, ma è un errore comune, in particolare da parte di persone provenienti da altre lingue.
String
build da stringa letterale verrà aggiunto a qualcosa chiamato String constant pool
, ad esempio, String s1 = "someString"; String s2 = "someString;"
entrambi s1
e s2
condividerà lo stesso riferimento. s1 == s2
tornerà vero. Ma se sono stati costruiti tramite String constructor
, ad esempio String s1 = new String("someString"); String s2 = new String("someString");
, non condivideranno lo stesso riferimento. s1 == s2
restituirà false.
Ci sono alcune piccole differenze a seconda che tu stia parlando di "primitivi" o "Tipi di oggetti"; lo stesso si può dire se si parla di membri "statici" o "non statici"; puoi anche mescolare tutto quanto sopra ...
Ecco un esempio (puoi eseguirlo):
public final class MyEqualityTest
{
public static void main( String args[] )
{
String s1 = new String( "Test" );
String s2 = new String( "Test" );
System.out.println( "\n1 - PRIMITIVES ");
System.out.println( s1 == s2 ); // false
System.out.println( s1.equals( s2 )); // true
A a1 = new A();
A a2 = new A();
System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
System.out.println( a1 == a2 ); // false
System.out.println( a1.s == a2.s ); // true
System.out.println( a1.s.equals( a2.s ) ); // true
B b1 = new B();
B b2 = new B();
System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
System.out.println( b1 == b2 ); // false
System.out.println( b1.getS() == b2.getS() ); // false
System.out.println( b1.getS().equals( b2.getS() ) ); // true
}
}
final class A
{
// static
public static String s;
A()
{
this.s = new String( "aTest" );
}
}
final class B
{
private String s;
B()
{
this.s = new String( "aTest" );
}
public String getS()
{
return s;
}
}
È possibile confrontare le spiegazioni per "==" (Operatore di uguaglianza) e ".equals (...)" (metodo nella classe java.lang.Object) tramite questi collegamenti:
La differenza tra == e uguale mi ha confuso per qualche tempo fino a quando ho deciso di dare un'occhiata più da vicino. Molti di loro dicono che per confrontare le stringhe dovresti usare equals
e non ==
. Spero in questa risposta che sarò in grado di dire la differenza.
Il modo migliore per rispondere a questa domanda sarà ponendoti alcune domande. quindi iniziamo:
Qual è l'output per il programma seguente:
String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);
se dici,
false
true
Dirò che hai ragione, ma perché l'hai detto ? e se dici che l'output è,
true
false
Dirò che hai torto ma ti chiederò ancora, perché pensi che sia giusto?
Ok, proviamo a rispondere a questo:
Qual è l'output per il programma seguente:
String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);
Ora se dici
false
true
Dirò che hai torto ma perché adesso è sbagliato ? l'uscita corretta per questo programma è
true
false
Si prega di confrontare il programma sopra e provare a pensarci.
Ok. Ora questo potrebbe aiutare (per favore leggi questo: stampa l'indirizzo dell'oggetto - non è possibile ma possiamo ancora usarlo.)
String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));
puoi provare a pensare all'output delle ultime tre righe nel codice sopra: per me ideone lo ha stampato ( puoi controllare il codice qui ):
false
true
true
false
mango mango
false
true
17225372
17225372
5433634
Oh! Ora vedi identityHashCode (mango) è uguale a identityHashCode (mango2) Ma non è uguale a identityHashCode (mango3)
Anche se tutte le variabili stringa - mango, mango2 e mango3 - hanno lo stesso valore, che è "mango", non identityHashCode()
è ancora lo stesso per tutti.
Ora prova a decommentare questa riga // mango2 = "mang";
ed eseguirla nuovamente questa volta vedrai che tutti e tre identityHashCode()
sono diversi. Questo è un suggerimento utile
sappiamo che se hashcode(x)=N
e hashcode(y)=N
=>x is equal to y
Non sono sicuro di come java funzioni internamente, ma presumo che sia quello che è successo quando ho detto:
mango = "mango";
java ha creato una stringa "mango"
che è stata puntata (referenziata) dalla variabile mango
qualcosa del genere
mango ----> "mango"
Ora nella riga successiva quando ho detto:
mango2 = "mango";
In realtà ha riutilizzato la stessa stringa "mango"
che assomiglia a qualcosa del genere
mango ----> "mango" <---- mango2
Sia mango che mango2 puntano allo stesso riferimento Ora quando ho detto
mango3 = new String("mango")
In realtà ha creato un riferimento (stringa) completamente nuovo per "mango". che assomiglia a qualcosa del genere,
mango -----> "mango" <------ mango2
mango3 ------> "mango"
ed è per questo che quando ho messo fuori i valori per mango == mango2
, ha messo fuori true
. e quando metto fuori il valore per mango3 == mango2
, lo mette fuori false
(anche quando i valori erano gli stessi).
e quando hai decommentato la linea // mango2 = "mang";
In realtà ha creato una stringa "mang" che ha trasformato il nostro grafico in questo modo:
mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"
Ecco perché identityHashCode non è uguale per tutti.
Spero che questo vi aiuti ragazzi. In realtà, volevo generare un caso di test in cui == fallisce e equals () passa. Non esitate a commentare e fatemi sapere se sbaglio.
mango == mango2
perché non hai creato mango2
come nuovo oggetto String e invece hai fatto direttamente riferimento "mango"
?
L' operatore == verifica se due variabili hanno gli stessi riferimenti (ovvero puntatore a un indirizzo di memoria) .
String foo = new String("abc");
String bar = new String("abc");
if(foo==bar)
// False (The objects are not the same)
bar = foo;
if(foo==bar)
// True (Now the objects are the same)
Considerando che il metodo equals () verifica se due variabili si riferiscono a oggetti che hanno lo stesso stato (valori) .
String foo = new String("abc");
String bar = new String("abc");
if(foo.equals(bar))
// True (The objects are identical but not same)
Saluti :-)
Dovrai sovrascrivere la funzione uguale (insieme ad altri) per usarla con le classi personalizzate.
Il metodo equals confronta gli oggetti.
L' ==
operatore binario confronta gli indirizzi di memoria.
Sia == che .equals () si riferiscono allo stesso oggetto se non si ignora .equals ().
È il tuo desiderio quello che vuoi fare dopo aver sostituito .equals (). Puoi confrontare lo stato dell'oggetto invocante con lo stato dell'oggetto passato oppure puoi semplicemente chiamare super.equals ()
String w1 ="Sarat";
String w2 ="Sarat";
String w3 = new String("Sarat");
System.out.println(w1.hashCode()); //3254818
System.out.println(w2.hashCode()); //3254818
System.out.println(w3.hashCode()); //3254818
System.out.println(System.identityHashCode(w1)); //prints 705927765
System.out.println(System.identityHashCode(w2)); //prints 705927765
System.out.println(System.identityHashCode(w3)); //prints 366712642
if(w1==w2) // (705927765==705927765)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
if(w2==w3) // (705927765==366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints false
if(w2.equals(w3)) // (Content of 705927765== Content of 366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
Ricorda solo che .equals(...)
deve essere implementato dalla classe che stai cercando di confrontare. Altrimenti, non ha molto senso; la versione del metodo per la classe Object fa la stessa cosa dell'operazione di confronto: Object # equivale .
L'unica volta in cui vuoi davvero usare l'operatore di confronto per gli oggetti è quando stai confrontando Enum. Questo perché esiste solo un'istanza di un valore Enum alla volta. Ad esempio, dato l'enum
enum FooEnum {A, B, C}
Non avrai mai più di un'istanza A
alla volta e lo stesso per B
e C
. Ciò significa che puoi effettivamente scrivere un metodo in questo modo:
public boolean compareFoos(FooEnum x, FooEnum y)
{
return (x == y);
}
E non avrai nessun problema.
Quando si valuta il codice, è molto chiaro che (==) viene confrontato in base all'indirizzo di memoria, mentre equals (Object o) confronta hashCode () delle istanze. Ecco perché si dice non rompere il contratto tra equals () e hashCode () se non si affrontano sorprese in seguito.
String s1 = new String("Ali");
String s2 = new String("Veli");
String s3 = new String("Ali");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println("(s1==s2):" + (s1 == s2));
System.out.println("(s1==s3):" + (s1 == s3));
System.out.println("s1.equals(s2):" + (s1.equals(s2)));
System.out.println("s1.equal(s3):" + (s1.equals(s3)));
/*Output
96670
3615852
96670
(s1==s2):false
(s1==s3):false
s1.equals(s2):false
s1.equal(s3):true
*/
Ecco un pollice generale di regola per la differenza tra relational operator ==
e the method .equals()
.
object1 == object2
confronta se gli oggetti a cui fanno riferimento object1 e object2 fanno riferimento alla stessa posizione di memoria in Heap .
object1.equals(object2)
confronta i valori di object1 e object2 indipendentemente da dove si trovano nella memoria .
Questo può essere dimostrato bene usando String
scenario 1
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = new String("Hello");
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? false
is str1.equals(str2) ? true
Scenario 2
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? true
is str1.equals(str2) ? true
Questo confronto di stringhe potrebbe essere usato come base per confrontare altri tipi di oggetti.
Ad esempio, se ho una classe Person , devo definire i criteri in base ai quali confronterò due persone . Supponiamo che questa classe di persone abbia variabili di istanza di altezza e peso.
Quindi creando oggetti persona person1 and person2
e per confrontare questi due usando l' .equals()
ho bisogno di scavalcare il metodo uguale della classe persona per definire in base a quali variabili di istanza (altezza o peso) sarà il confronto.
Tuttavia, il == operator will still return results based on the memory location of the two objects(person1 and person2)
.
Per facilitare la generalizzazione di questo confronto di oggetti persona, ho creato la seguente classe di test. Sperimentare questi concetti rivelerà tonnellate di fatti .
package com.tadtab.CS5044;
public class Person {
private double height;
private double weight;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(height);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
/**
* This method uses the height as a means of comparing person objects.
* NOTE: weight is not part of the comparison criteria
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
return false;
return true;
}
public static void main(String[] args) {
Person person1 = new Person();
person1.setHeight(5.50);
person1.setWeight(140.00);
Person person2 = new Person();
person2.setHeight(5.70);
person2.setWeight(160.00);
Person person3 = new Person();
person3 = person2;
Person person4 = new Person();
person4.setHeight(5.70);
Person person5 = new Person();
person5.setWeight(160.00);
System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
System.out.println("is person2 == person3 ? " + (person2 == person3)); // true
//this is because perosn3 and person to refer to the one person object in memory. They are aliases;
System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;
System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;
// even if the person2 and person5 have the same weight, they are not equal.
// it is because their height is different
System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}
}
Il risultato di questa esecuzione di classe è:
is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
== l'operatore fa sempre riferimento. Ma in caso di
metodo equals ()
dipende dall'implementazione se il metodo è uguale a override rispetto a quello che confronta l'oggetto sulla base dell'implementazione fornita nel metodo override.
class A
{
int id;
String str;
public A(int id,String str)
{
this.id=id;
this.str=str;
}
public static void main(String arg[])
{
A obj=new A(101,"sam");
A obj1=new A(101,"sam");
obj.equals(obj1)//fasle
obj==obj1 // fasle
}
}
nel codice sopra sia obj che obj1 contengono gli stessi dati ma il riferimento non è lo stesso quindi equivale a restituire false e == anche. ma se abbiamo ignorato il metodo uguale a
class A
{
int id;
String str;
public A(int id,String str)
{
this.id=id;
this.str=str;
}
public boolean equals(Object obj)
{
A a1=(A)obj;
return this.id==a1.id;
}
public static void main(String arg[])
{
A obj=new A(101,"sam");
A obj1=new A(101,"sam");
obj.equals(obj1)//true
obj==obj1 // fasle
}
}
so check out restituirà vero e falso per lo stesso caso solo noi abbiamo ignorato
metodo uguale.
confronta l'oggetto sulla base del contenuto (id) dell'oggetto
ma ==
ancora confrontare i riferimenti di oggetto.
La differenza principale tra == e equals () è
1) == viene utilizzato per confrontare le primitive.
Per esempio :
String string1 = "Ravi";
String string2 = "Ravi";
String string3 = new String("Ravi");
String string4 = new String("Prakash");
System.out.println(string1 == string2); // true because same reference in string pool
System.out.println(string1 == string3); // false
2) equals () viene utilizzato per confrontare gli oggetti. Per esempio :
System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects
System.out.println(string1.equals(string3)); // true
System.out.println(string1.equals(string4)); // false
==
può essere utilizzato in molti tipi di oggetti ma è possibile utilizzarlo Object.equals
per qualsiasi tipo, in particolare stringhe e indicatori di mappe di Google.
public class StringPool {
public static void main(String[] args) {
String s1 = "Cat";// will create reference in string pool of heap memory
String s2 = "Cat";
String s3 = new String("Cat");//will create a object in heap memory
// Using == will give us true because same reference in string pool
if (s1 == s2) {
System.out.println("true");
} else {
System.out.println("false");
}
// Using == with reference and Object will give us False
if (s1 == s3) {
System.out.println("true");
} else {
System.out.println("false");
}
// Using .equals method which refers to value
if (s1.equals(s3)) {
System.out.println("true");
} else {
System.out.println("False");
}
}
}
---- Uscita ----- vero falso vero
Potrebbe valere la pena aggiungere che per gli oggetti wrapper per tipi primitivi - ovvero Int, Long, Double - == restituirà true se i due valori sono uguali.
Long a = 10L;
Long b = 10L;
if (a == b) {
System.out.println("Wrapped primitives behave like values");
}
Al contrario, mettendo i due Long sopra indicati in due distinte ArrayList, equivale a vederli uguali, ma == no.
ArrayList<Long> c = new ArrayList<>();
ArrayList<Long> d = new ArrayList<>();
c.add(a);
d.add(b);
if (c == d) System.out.println("No way!");
if (c.equals(d)) System.out.println("Yes, this is true.");
Long a = 128l; Long b = 128l; System.out.println(a == b);
Il pool di stringhe (noto anche come interning ) e il pool di numeri interi offuscano ulteriormente la differenza e ==
in alcuni casi potrebbero consentire l'utilizzo da parte degli oggetti anziché.equals
Questo può darti maggiori prestazioni (?), A costo di una maggiore complessità.
Per esempio:
assert "ab" == "a" + "b";
Integer i = 1;
Integer j = i;
assert i == j;
Complessità della complessità: quanto segue potrebbe sorprenderti:
assert new String("a") != new String("a");
Integer i = 128;
Integer j = 128;
assert i != j;
Ti consiglio di stare lontano da tale micro-ottimizzazione e di usarlo sempre.equals
per gli oggetti e ==
per i primitivi:
assert (new String("a")).equals(new String("a"));
Integer i = 128;
Integer j = 128;
assert i.equals(j);
In breve, la risposta è "Sì".
In Java, l' ==
operatore confronta i due oggetti per vedere se puntano alla stessa posizione di memoria; mentre il .equals()
metodo confronta effettivamente i due oggetti per vedere se hanno lo stesso valore di oggetto.
Fondamentalmente, ==
confronta se due oggetti hanno lo stesso riferimento sull'heap, quindi a meno che due riferimenti non siano collegati allo stesso oggetto, questo confronto sarà falso.
equals()
è un metodo ereditato dalla Object
classe. Questo metodo per impostazione predefinita confronta se due oggetti hanno lo stesso referece. Significa:
object1.equals(object2)
<=> object1 == object2
Tuttavia, se si desidera stabilire la parità tra due oggetti della stessa classe, è necessario ignorare questo metodo. È anche molto importante sostituire il metodohashCode()
caso di overridenequals()
.
Implementare hashCode()
quando si stabilisce l'uguaglianza fa parte del contratto oggetto Java. Se stai lavorando con raccolte e non hai implementato hashCode()
, potrebbero accadere cose strane:
HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat, "This is a cool cat");
System.out.println(cats.get(new Cat("molly"));
null
verrà stampato dopo aver eseguito il codice precedente se non è stato implementato hashCode()
.
Poiché Java non supporta il sovraccarico dell'operatore, == si comporta in modo identico per ogni oggetto ma equals () è il metodo, che può essere sovrascritto in Java e la logica per confrontare gli oggetti può essere modificata in base alle regole aziendali.
La principale differenza tra == e uguale a Java è che "==" viene utilizzato per confrontare le primitive mentre il metodo equals () è raccomandato per verificare l'uguaglianza degli oggetti.
Il confronto tra stringhe è uno scenario comune di utilizzo sia del metodo == sia di uguale. Poiché la sovrascrittura della classe java.lang.String equivale al metodo, restituisce true se l'oggetto String due contiene lo stesso contenuto ma == restituirà true solo se due riferimenti puntano allo stesso oggetto.
Ecco un esempio di confronto tra due stringhe in Java per uguaglianza usando il metodo == e equals () che chiarirà alcuni dubbi:
public class TEstT{
public static void main(String[] args) {
String text1 = new String("apple");
String text2 = new String("apple");
//since two strings are different object result should be false
boolean result = text1 == text2;
System.out.println("Comparing two strings with == operator: " + result);
//since strings contains same content , equals() should return true
result = text1.equals(text2);
System.out.println("Comparing two Strings with same content using equals method: " + result);
text2 = text1;
//since both text2 and text1d reference variable are pointing to same object
//"==" should return true
result = (text1 == text2);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);
}
}