Ebensowenig kann man Objekte mit == vergleichen, da so nur ihre
Referenzen verglichen werden, d.h. der Vergleich ist genau dann wahr, wenn
das Objekt mit sich selbst verglichen wird.
Es gibt aber eine Methode der Klasse Object, nämlich
boolean equals(Object o), die man in eigenen
Klassen überschreiben kann. (Die allgemeine Methode aus Object
vergleicht nur die Referenzen.) Es gibt kein zu Cloneable analoges
Interface Comparable o.ä.
Vorsicht: Auch in einer Klasse X muß
equals() als Parameter Object erhalten, da die
allgemeine Methode sonst nicht überschrieben, sondern überladen wird!
Folgendes Beispiel implementiert clone() und
equals() für eine Klasse ClassX:
- class ClassX implements Cloneable
{
private int data;
public ClassX(int i) { data=i; }
public Object clone() { return new ClassX(data); }
public void set(int i) { data=i; }
public String toString() { return (new Integer(data).toString()); }
public boolean equals(Object x2) { return data==((ClassX)x2).data; }
}
public class test
{
public static void main(String[] args)
{
ClassX a=new ClassX(3);
ClassX b=(ClassX)a.clone();
a.set(5);
System.out.println(a); // Ausgabe: 5
System.out.println(b); // Ausgabe: 3
System.out.println(a.equals(b)); // Ausgabe: false
b.set(5);
System.out.println(a.equals(b)); // Ausgabe: true
}
}
Unsere Methode equals() ist so nur für Vergleiche mit anderen
Objekten der Klasse ClassX verwendbar. Die Typumwandlung
(ClassX)x2 ist nämlich nur erlaubt, wenn x2
tatsächlich ein ClassX-Objekt ist und nur der Schnittstelle halber
als Object-Referenz bei uns angekommen ist. Bei einer
null-Referenz wird eine NullPointerException, bei fremden
Klassen eine ClassCastException ausgelöst. Will man ein
equals() schreiben, das mit beliebigen Referenzen funktioniert,
geht man wie folgt vor:
- public boolean equals(Object x2)
{
if ( x2!=null && (x2 instanceof ClassX) )
return data==((ClassX)x2).data;
return false;
}
Eine Bemerkung zu toString() aus unserem Beispiel: Dabei handelt
es sich um eine Methode der Klasse Object.
Diese allgemeine Version gibt aber nur
den Namen der eigentlichen Klasse aus, der das Objekt angehört, und
hexadezimal die Adresse, durch die die Referenz darauf dargestellt wird,
z.B.: java.lang.Object@1cc73e
Um eine sinnvolle Text-Repräsentation zur Verfügung zu stellen, sollte
die Methode in eigenen Klassen überschrieben werden (wie hier).
Sie wird z.B. verwendet, wenn ein Objekt auf einen Stream
ausgegeben werden soll (eben mit System.out.println)
und in String-Verkettungen (wie "("+o+")").