# equals überschreiben



## André Uhres (11. Mai 2007)

*abgtrennt von http://www.java-forum.org/de/topic48918_tostring.html*





			
				Tobias hat gesagt.:
			
		

> ..Kleiner Tip: Alle eingebauten Java-Klassen haben sinnvolle toString()-Methoden..


Das sollten eigentlich auch alle selbst geschriebenen Klassen haben  :wink:


----------



## Tobias (11. Mai 2007)

Sie sollten auch sinnvolle equals()- und hashCode()-Implementierungen haben. Nur wer tut das wirklich? :roll:

mpG
Tobias


----------



## Gast (11. Mai 2007)

Wenn man ne klasse schreibt und die niemals per toString ausgeben will braucht man auch keine toString() Methode dafür schreiben.

Ebenso mit equals/hashcode


----------



## bygones (11. Mai 2007)

Gast hat gesagt.:
			
		

> Wenn man ne klasse schreibt und die niemals per toString ausgeben will braucht man auch keine toString() Methode dafür schreiben.
> 
> Ebenso mit equals/hashcode


bis man dann monate spaeter auf die idee kommt mal seine Objekte in Sets oder Maps zu stecken und dann sich Fehler nicht erklaeren kann...


----------



## Guest (12. Mai 2007)

deathbyaclown hat gesagt.:
			
		

> Gast hat gesagt.:
> 
> 
> 
> ...



sowas passiert wenn man nur equals aber nicht hashcode überschreibt, wenn man keines von beiden überschreibt funktionert das natürlich ohne probleme


----------



## Leroy42 (12. Mai 2007)

Anonymous hat gesagt.:
			
		

> sowas passiert wenn man nur equals aber nicht hashcode überschreibt, wenn man keines von beiden überschreibt funktionert das natürlich ohne probleme



Richtig!

Aber ob die Ergebnisse auch im Sinne des Erfinders sind?  ???:L (  )


----------



## bygones (14. Mai 2007)

Anonymous hat gesagt.:
			
		

> deathbyaclown hat gesagt.:
> 
> 
> 
> ...


vll versteh ich dich falsch, aber zu sagen, nix zu ueberschreiben und dann klappts ohne probleme stimmt nicht


```
public class TestClass {
    public static void main( String[] args ) throws IOException {
        Map<Te, String> tt = new HashMap<Te, String> ();
        
        tt.put(new Te("123"), "45");
        System.out.println(tt.containsKey(new Te("123")));
    }    
}

class Te {
    private String t;
    
    public Te(String t) {
        this.t = t;
    }
}
```
Ausgabe ist false...


----------



## byte (14. Mai 2007)

deathbyaclown hat gesagt.:
			
		

> Gast hat gesagt.:
> 
> 
> 
> ...



Aber bei großen Objektstrukturen mit Zyklen ist es nicht umbedingt trivial, equals() sinnvoll zu überschreiben. Insofern ist es nicht gerade zeiteffektiv, sich die Arbeit zu machen, wenn man es zunächst erstmal gar nicht benötigt. Aber wenn man langfristig denkt, hast Du natürlich recht.


----------



## kleiner_held (14. Mai 2007)

@deathbyaclown

Ersetze in deinem Beispiel den Klassennamen _Te_ durch _Person_ und das Attribut _t_ durch _vorname_ und erklaer mir warum es nicht zwei Personen namens "Torsten" in deiner Map geben darf.

Es kann genau so ein Fehler sein, equals() und hashCode() zu ueberschreiben, wie es ein Fehler sein kann sie nicht zu ueberschreiben.


----------



## Leroy42 (14. Mai 2007)

kleiner_held hat gesagt.:
			
		

> warum es nicht zwei Personen namens "Torsten" in deiner Map geben darf.



Hmmh!  ???:L 
Vielleicht weil _Torsten_ eine DDR-Erfindung war und es richtig _T*h*orsten_ heißt?


----------



## kleiner_held (14. Mai 2007)

Leroy42 hat gesagt.:
			
		

> Hmmh!  ???:L
> Vielleicht weil _Torsten_ eine DDR-Erfindung war und es richtig _T*h*orsten_ heißt?


Oh Mann - jatzt hast Du mich aber in Grund und Boden argumentiert.  :? 
Aber nagut - 1. listet mir der Wikipedia Artikel zu Thorsten immerhin 5 Torsten's ohne h die vor 1945 geboren sind (also nix mit DDR-Erfindung) und zweitens besteht bei insgesammt 53 Torsten's in dieser Liste (und uebrigens nur 41 Thorsten's) immernoch die Notwendigkeit fuer mehrere Torsten's in der Map.


----------



## André Uhres (14. Mai 2007)

API hat gesagt.:
			
		

> public interface Map
> 
> An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.


----------



## Leroy42 (14. Mai 2007)

kleiner_held hat gesagt.:
			
		

> immernoch die Notwendigkeit fuer mehrere Torsten's in der Map.



Ja natürlich! Das wollte ich ja auch gar nicht in Abrede stellen.   



			
				kleiner_held hat gesagt.:
			
		

> immerhin 5 Torsten's ohne h die vor 1945 geboren sind



Ehrlich? Da hab' ich mir wohl ein Bären (von wegen DDR) aufbinden lassen.

Ich ging immer davon aus, daß Thorsten auf den Gott _Thor_ 
(der altgermanische Hammerwerfer   ) zurückgeht und deshalb
Thorsten mit s geschrieben werden müßte.


----------



## kleiner_held (14. Mai 2007)

@Leroy42
keine Sorge, ich weiss schon wie es gemeint war. ;-)
Naja wer will schon definieren wie ein Name richtig geschrieben wird, wenn die meisten Name aus einer Zeit stammen, in der sowieso jeder schrieb wie er wollte (d.h. die 3% die schreiben konnten).

So jetzt ist aber Schluss mit Offtopic


----------



## Tellerrand (14. Mai 2007)

kleiner_held hat gesagt.:
			
		

> Es kann genau so ein Fehler sein, equals() und heshCode() zu ueberschreiben, wie es ein Fehler sein kann sie nicht zu ueberschreiben.


Equals und hashCode haben doch vorgegebene Aufgaben die sie erledigen sollen.
Nur weil man dann eine falsche Datenstruktur für ein Problem wählt, hier die Map mit Vornamen als Schlüssel würde ich nicht dazu raten den Sinn von toString und hashCode zu vergessen.

Am Ende hat man dann das Problem, dass Programmteil A vernünftige toString und hashCode Implementierungen vorraussetzt und Programmteil B eben andere.
Da implementiert man toString und hashCode lieber ordentlich und denkt sich für Programmteil B was neues aus.
(Dank Zeugs wie Eclipse ist das auch nicht viel Aufwand. Da kann man sich den Hauptteil der Arbeit auch mal abnehmen lassen)

EDIT: wups, meinte eigentlich equals anstatt toString


----------



## kleiner_held (14. Mai 2007)

Ich wollte mit meinem krummen Beispiel eigentlich auch nur sagen, das die default Implementierung von hashCode und equals in vielen Faellen die vernuenftigste ist.
 Ich verstehe gar nicht wieso man bei diesen Methoden ein Objekt immer nur auf seine Attribute beschraenken soll - sehr oft ist es halt am sinvollsten, dass equals nur gilt wenn Instanzgleichheit vorhanden ist.

Im Gegenteil habe ich aber schon viele Implementierungen gesehen, die equals ueberschreiben und dort mit Instanzvariablen arbeiten, obwohl diese aenderbar sind und auch geaendert werden. Das widerspricht aber der Konsistenzbedingung in equals() (siehe JavaDoc). Wie oft mir unterkam das jemand equals()  ueberschrieben hat, aber nicht hashCode() kann ich gar nicht mehr zaehlen.

Aus diesen Gruenden plädiere ich im Allgemeinen dafuer, dass man equals() und hashCode() auch nur dann ueberschreibt, wenn es wirklich noetig ist. Einer Aussage "equals() und hashCode() sollte man immer ueberschreiben" kann ich mich definitiv nicht anschliessen.


----------



## byte (14. Mai 2007)

kleiner_held hat gesagt.:
			
		

> Im Gegenteil habe ich aber schon viele Implementierungen gesehen, die equals ueberschreiben und dort mit Instanzvariablen arbeiten, obwohl diese aenderbar sind und auch geaendert werden. Das widerspricht aber der Konsistenzbedingung in equals() (siehe JavaDoc).



Der Sinn von equals() ist doch nun mal der Vergleich auf inhaltliche Gleichheit. Der Inhalt eines Objekts definiert sich über seine Member, insofern vergleichst Du diese, wenn Du equals() überschreibst.
Wenn Du equals() nicht überschreibst, dann brauchst du es gar nicht erst benutzen und kannst Dich auf == beschränken.




> Einer Aussage "equals() und hashCode() sollte man immer ueberschreiben" kann ich mich definitiv nicht anschliessen.



... ist aber laut vieler Java-Gurus Best Practice, sie zu überschreiben. Und ich kann das auch gut nachvollziehen, denn der elementarste Teil von Java ist wohl das Collection-Framework. Und nur durch das Überschreiben von equals() und hashcode() kannst Du sicherstellen, dass deine Objekte wie gewünscht mit allen Collections funktionieren. Und zumindest bei zyklenfreien Objektstrukturen hast Du dadurch nicht mal Arbeit, zumindest Eclipse übernimmt die Implementierung dann auf Knopfdruck.


----------



## kleiner_held (14. Mai 2007)

ok dann geht es hier weiter ;-)

Eine Definition was "is equal" in Java bedeutet ist nicht festgelegt - es ist explizit jeder Klasse selbst ueberlassen.
Wenn ich Klassen habe, die primaer zur Datenhaltung verwendet werden, macht das Ueberschreiben meist Sinn (und ich verwende dann meistens ein ID Attribut welches sich nie aendert - siehe Konsistenzanforderung), in vielen anderen Faellen nicht.

Man schaue sich nur die Standardklassen von Java an:
- java.util.* da ueberschreiben so ziemlich alle Klassen equals, ist auch logisch schliesslich sind es fast alles Collections und andere Container Klassen
- java.io.* keiner von den Streams/Readern/Writern ueberschreibt die Methoden - sie sind halt nicht equal auch wenn alle Attribute gleich sind (Wenn 2 FileReader von der gleichen Datei lesen sind sie nicht equal)
- java.awt.* javax.swing.* keine der Komponenten ueberschreibt equals, obwohl man ein JLabel sicherlich anhand von Farbe, Schriftart, Anzeigetext vergleichen koennte. Es ist aber halt grad nicht gewuenscht, dass man keine 2 JLabels in ein Set packen kann, bloss weil sie zufaelligerweise den gleichen Text auf die gleiche Art darstellen.


----------



## byte (14. Mai 2007)

Einen guten Punkt sprichst Du da an. Ich schränke meine Aussage von oben mal auf Objekte des Datenmodells ein. Ich wäre auch nie auf die Idee gekommen, die equals() in einer GUI Klassen zu überschreiben.


----------



## SlaterB (14. Mai 2007)

> Und nur durch das Überschreiben von equals() und hashcode() kannst Du sicherstellen, dass deine Objekte wie gewünscht mit allen Collections funktionieren. 

naja, kommt auf die Art des Funktionierens an 

wenn es keine argen Probleme geben soll 
(z.B. unter anderem Hashcode abgespeichert als jetzt aktuell/
equals stimmt, aber Hashcode nicht gleich)
dann gibt es nur eine sichere Methode: nämlich genau die Operationen NICHT zu überschreiben 

die Ursprungsoperationen sind sicher, alles andere nicht

--------

wenn es dagegen um die inhaltliche Aufgabe geht, unterschiedliche Objekte gleichen Inhalts anzugleichen, dann braucht man leider die Operationen,
dann ist es notwendig, equals und hashcode zu überschreiben,
aber die Worte 'kannst Du sicherstellen' finde ich da immer noch unpassend


----------



## Tellerrand (14. Mai 2007)

byto hat gesagt.:
			
		

> Einen guten Punkt sprichst Du da an. Ich schränke meine Aussage von oben mal auf Objekte des Datenmodells ein. Ich wäre auch nie auf die Idee gekommen, die equals() in einer GUI Klassen zu überschreiben.


Jup, ich beschränke mich bei equals() auch auf Klassen, bei denen eine logische Gleichheit Sinn macht, also im Bereich des Models.

Im Zusammenhang mit relationalen Datenbanken behandle ich das übrigens auch wie geschrieben mit einem einfachen Vergleich des vorhandenen (zusammengesetzen) Primärschlüssels.


----------



## kleiner_held (14. Mai 2007)

OK beim Datenmodell ist es natuerlich schon sinvoll, vor allem in Verbindung mit den PK Attributen der Datenbankschicht. Auch die VO Generierung von XDoclet geht diesen Weg.


----------



## Tellerrand (14. Mai 2007)

SlaterB hat gesagt.:
			
		

> wenn es keine argen Probleme geben soll
> (z.B. unter anderem Hashcode abgespeichert als jetzt aktuell/
> equals stimmt, aber Hashcode nicht gleich)
> dann gibt es nur eine sichere Methode: nämlich genau die Operationen NICHT zu überschreiben


Eine richtige Implementation von equals und hashCode setzt doch gerade vorraus, dass wenn equals stimmt hashCode eben auch die selben Werte liefert.
Oder was meinst du nun genau?


----------



## SlaterB (14. Mai 2007)

ich meinte nur, dass jede noch so 'gute' Implementation nicht  sicherer ist als gar keine Implementatation,
denn diese ist ja erwiesen sicher, da gibts keine Steigerung,

also macht ein Satz wie 'nur durch das Überschreiben von equals() und hashcode() kannst Du sicherstellen, dass deine Objekte wie gewünscht mit allen Collections funktionieren. '
keinen Sinn, denn ohne überschreiben funktionieren sie objektiv gesehen am besten,

sie funktionieren korrekt, nur leider vielleicht gar nicht im Sinne der gewüschten Anwendung,
allein aus diesem Grund überschreibt man dann die Operationen,


----------



## byte (14. Mai 2007)

> The default hashCode() method uses the 32-bit internal JVM address of the Object as its hashCode. However, if the Object is moved in memory during garbage collection, the hashCode stays constant. This default hashCode is not very useful, since to look up an Object in a HashMap, you need the exact same key Object by which the key/value pair was originally filed. Normally, when you go to look up, you don't have the original key Object itself, just some data for a key. *So, unless your key is a String, nearly always you will need to implement a hashCode and equals method on your key class.*



Quelle: http://mindprod.com/jgloss/hashcode.html


----------



## SlaterB (14. Mai 2007)

das wäre natürlcih was anderes, 
aber dann würde ganz Java ja nicht mehr funktionieren,
hat das praktische Relevanz oder ist das ein akademischer Fall?

edit: ach Quatsch, da steht ja nicht, dass sich der Hashcode verändert,
sondern da wird nur das Standardverhalten beschrieben,

wie gesagt: ja wenn man ein Objekt mit anderen gleichen Daten finden will, dann muss es sein, klar,
aber das hat mit der prinzipiellen Funktionalität der Map nix zu tun,

(mit der praktischen schon  )


----------



## Tobias (14. Mai 2007)

kleiner_held:


> Im Gegenteil habe ich aber schon viele Implementierungen gesehen, die equals ueberschreiben und dort mit Instanzvariablen arbeiten, obwohl diese aenderbar sind und auch geaendert werden. Das widerspricht aber der Konsistenzbedingung in equals() (siehe JavaDoc).



Meinst du die hier?



> It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true  or consistently return false,



dann hast du aber das hier übersehen



> provided no information used in equals comparisons on the objects is modified.



mpG
Tobias


----------



## kleiner_held (15. Mai 2007)

Ich meine die Kombination aus der von dir angesprochenen Bedingung:


			
				Java Doc zu equals hat gesagt.:
			
		

> It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true  or consistently return false, provided no information used in equals comparisons on the objects is modified.



und


			
				Java Doc zu Set hat gesagt.:
			
		

> Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.



Das gleiche bei Map. 

In dem Zusammenhang bin ich halt eher fuer eine sehr restriktive Handhabung von equals (also Konsistenz auch trotzt der Aenderung von mutable Properties) - auch weil ich schon mal viel Schweiss gelassen habe, um eine derartige Fehlerquelle zu finden. Solche Erfahrungen prägen halt 

Ich bin mir schon bewusst, das gerade die Collections das nicht so handhaben und alle Collections fleissig ihren HashCode aendern, sobald man Elemente enfernt/hinzufuegt (oder halt der HashCode eines Elements sich aendert), aber das ist halt der Preis fuer die, zugegebenermassen sehr nuetzliche, inhaltsabhaengige Implementierung von equals bei den Collections.


----------



## Tellerrand (15. Mai 2007)

kleiner_held hat gesagt.:
			
		

> In dem Zusammenhang bin ich halt eher fuer eine sehr restriktive Handhabung von equals (also Konsistenz auch trotzt der Aenderung von mutable Properties) - auch weil ich schon mal viel Schweiss gelassen habe, um eine derartige Fehlerquelle zu finden. Solche Erfahrungen prägen halt


Das Problem liegt aber doch ganz woanderst.
Die Datenstruktur ist so definiert, dass doppelte Objekte (Keys, bei der Map) nicht vorkommen dürfen.
Da dies Probleme geben kann wenn man mit veränderbaren Objekten arbeitet ist klar.
(Und das ein Interface das Verhalten hier nicht definiert und den Programmierer warnt ist doch verständlich, da muss man sich schon die Implementierungen anschauen)

Jetzt gehst du den Weg einfach equals so zu definieren, dass es möglich ist zwei gleiche Objekte in ein Set, bzw eine Map zu stecken?

Wobei ich in diesem Zusammenhang "gleiche Objekte" nicht weiter definiere, denn im Prinziep ist es eben genau die equals Methode welche sich darum kümmern sollte.
Nur warum sollte man die Gleichheit von Objekten nach den verwendeten Datenstrukturen richten und nicht nach dem Objekt selber?

Es wird je nach Klasse entschieden wann zwei Objekte dieser Klasse gleich sind.
Dieser Grundsatz richtiet sich erstmal nur nach der Logik, ob man dann anhand der Attribute entscheidet oder nicht folgt nur daraus.

Da die vererbte equals Methode nur auf Instanzgleichheit prüft sollte man diese also überschreiben sobald zwei Objekte gleich sein können auch wenn es verschiedene Instanzen sind.

Das ist auch genau das was sun z.B bei deinen Beispielen gemacht hat:
- java.util.* hier sind die Objekte gleich wenn sie den selben Inhalt haben, daher ein richtiges equals.
- java.io.* die meisten Objekte sind nicht gleich, daher auch das standard equals.
- java.awt.* javax.swing.* die meisten Objekte sind nicht gleich, daher auch das standard equals.

Ein letztes Problem bleibt zwar immer offen: "Wann sind Objekte gleich" aber das ist halt die Frage die man sich bei jeder Klasse neu stellen muss.

EDIT: uiuiui ... krankes Hirn, verwirrender Text  :autsch:


----------



## kleiner_held (15. Mai 2007)

Naja mir geht es halt darum wie definiere ich am besten "gleich". Fuer meine eigenen Klassen bin ich ja frei das festzulegen. 
Beispiel die Klasse Person, ich habe Id, Name, Vorname usw.
Ich kann equals benutzen um innerhalb der Applikation die Identitaet der zugrundeliegenden DB Eintraege abzubilden indem ich nur auf das Id Attribut gehe.
Ich kann equals aber auch benutzen um den Gesamtzustand zu vergleichen indem ich alle Attribute in equals einfliessen lasse.

Der 2te Fall klingt zwar fuer verschiedene Szenarien ganz interessant, es gibt aber Seiteneffekte die einem vielleicht garnicht sofort auffallen. Deswegen bion ich in der Hinsicht der Meinung bei sowas die erste Variante zu verwenden und keine mutable Attribute ins equals einfliessen zu lassen. Und wenn es allgemein um eigene Klassen geht, also nicht speziell um Klassen des Datenmodells, dann halte ich es meistens fuer die beste Loesung equals und hashCode gar nicht zu ueberschreiben.

PS: hier mal ein Negaivbeispiel was einem mit aenderbaren Attributen in equals passiert:

```
public class HashMapSample
{
	public static void main(String[] args)
	{ 
		Set<Entry> set1 = new HashSet<Entry> ();
		Set<Entry> set2 = new HashSet<Entry> ();
		Entry entry1 = new Entry("Test");
		Entry entry2 = new Entry("Test");

		System.out.println("Result of add entry1 to set1 = " + set1.add(entry1));
		System.out.println("Result of add entry1 to set1 = " + set1.add(entry1));
		System.out.println("Result of add entry2 to set1 = " + set1.add(entry2));
		for (Entry entry : set1)
		{
			System.out.println("Set1 contains:"+entry.toString());
		}

		System.out.println("Result of add entry1 to set2 = " + set2.add(entry1));
		entry1.setContent("Toast");
		System.out.println("Result of add entry1 to set2 = " + set2.add(entry1));
		for (Entry entry : set2)
		{
			System.out.println("Set2 contains:"+entry.toString());
		}
	}
	
	private static class Entry 
	{
		private String content;

		public Entry(String content)
		{
			this.content = content;
		}

		public String getContent()
		{
			return content;
		}

		public void setContent(String content)
		{
			this.content = content;
		}
		
		public boolean equals(Object obj)
		{
			if (! (obj instanceof Entry))
			{
				return false;
			}
			return content.equals(((Entry) obj).content);
		}
		
		public int hashCode()
		{
			return content.hashCode();
		}
		
		public String toString()
		{
			return content;
		}
	}
}
```
Waehrend in Set1 alles erwartungsgemaess funktioniert, wirds bei Set2 ploetzlich richtig eklig. Und solche Fehlerursachen zu finden und zu fixen ist sehr aufwendig (denn in einer komplexen Applikationen im Nachhinein an equals Implementierungen rumzuaendern ist schon Sprengstoff). 

Und um jetzt mal den Bogen zum eigentlichen Ausloeser der Diskussion zu schlagen: 
Wenn man halt sagt: "Equals und hashCode soll man eigentlich immer ueberschreiben" provoziert man schnell Fehlerquellen wenn man nicht weiss was man tut bzw erreichen will. Manchmal ist es halt auch besser einfach equals nicht zu ueberschreiben, selbst wenn es im ersten Moment doch so elegant aussieht.


----------



## Tellerrand (15. Mai 2007)

kleiner_held hat gesagt.:
			
		

> Deswegen bion ich in der Hinsicht der Meinung bei sowas die erste Variante zu verwenden und keine mutable Attribute ins equals einfliessen zu lassen.


Wie gesagt, da stimme ich dir bedenkenlos zu. Wenn ich eine Art ID hab ist das gut.



			
				kleiner_held hat gesagt.:
			
		

> Waehrend in Set1 alles erwartungsgemaess funktioniert, wirds bei Set2 ploetzlich richtig eklig. Und solche Fehlerursachen zu finden und zu fixen ist sehr aufwendig (denn in einer komplexen Applikationen im Nachhinein an equals Implementierungen rumzuaendern ist schon Sprengstoff).



Ohne equals Implementation:


> Result of add entry1 to set1 = true
> Result of add entry1 to set1 = false
> Result of add entry2 to set1 = true
> *Set1 contains:Test
> ...


Warum sollte das hier schöner sein?



			
				kleiner_held hat gesagt.:
			
		

> Und um jetzt mal den Bogen zum eigentlichen Ausloeser der Diskussion zu schlagen:
> Wenn man halt sagt: "Equals und hashCode soll man eigentlich immer ueberschreiben" provoziert man schnell Fehlerquellen wenn man nicht weiss was man tut bzw erreichen will. Manchmal ist es halt auch besser einfach equals nicht zu ueberschreiben, selbst wenn es im ersten Moment doch so elegant aussieht.


Es komtm doch drauf an wie man equals überschreibt und nicht ob man dies tut.
Eine equals Implementierung kann auch so aussehen "if(this == obj) { return true; } return false;" was man sich aber sparen kann, da per default equals so implementiert ist.

Ich sage ja sobald die Gleichheit zweier Objekte schon früher gegeben ist sollte man equals überschreiben.
"[...] provoziert man schnell Fehlerquellen wenn man nicht weiss was man tut bzw erreichen will." Das ist immer und überall der Fall, wenn man nicht weiß was man tut sollte man es sein lassen ... klar.


----------



## André Uhres (19. Mai 2007)

Ich will das jetzt auch mal für "Nichtakademiker" verständlich zusammenfassen (ist ja jetzt "mein" Thread :wink: ):

Die Diskussion wurde ausgelöst durch den Hinweis, daß man "toString" immer überschreiben sollte.
Dann wurde gesagt, das müsse eigentlich auch für die "equals" Methode gelten (zusammen mit "hashCode").

Wenn man "equals" *nicht* überschreibt, dann ist jede Instanz nur gleich zu sich selbst.
In folgenden Fällen ist das die beste Wahl:

```
- Jede Instanz einer Klasse ist naturgemäss einzigartig. 
  Das gilt allgemein für Aktionsklassen, zum Beispiel für die Klasse "Thread".

- Die "logische Gleichheit" einer Klasse interessiert keinen. 
  Beispiel: java.util.Random hätte "equals" überschreiben können, damit man schauen kann, 
  ob zwei Random Instanzen die gleiche Folge von Zufallszahlen ergeben. 
  Das wurde aber nicht gemacht, weil man davon ausgeht, daß keiner das will.

- Eine Superklasse hat schon "equals" überschrieben und das ererbte Verhalten genügt dieser Klasse.

- Die Klasse ist "private" oder "package-private" und du bist sicher, 
  daß "equals" niemals aufgerufen wird. Man könnte in dem Fall "equals" aber auch so überschreiben, 
  daß sie eine "UnsupportedOperationException" wirft.
```

Wann sollte man denn eigentlich "equals" (und natürlich "hashCode" !) überschreiben? 
Allgemein wird man das bei Klassen tun wollen, die Werte darstellen (wie die Klasse "Integer" oder "Date").
Wenn man Referenzen zu Objekten vergleicht, die Werte darstellen, dann interessiert einen gewöhnlich,
ob sie "logisch gleich" sind, und nicht, ob sie sie auf das gleiche Objekt zeigen.


----------

