Warum gibst hier Equals false zurück ?

Bullz

Mitglied
hallo, 😉 vielleicht kleine Vorstellung. Bin neu hier und arbeite mich gerade in Java ein. Mir ist nicht klar wie folgender Ausdruck false sein kann ...

Java:
public class Typen {
    
    public static void main(String[] args) {
        
        Cabrio a = new Cabrio("abc"); 
        Cabrio b = new Cabrio("abc");
        
        System.out.println(a.equals(b));  // sollte doch true sein ist es aber nicht.
        System.out.println(a==b);         // Referenzen werden verglichen und das ist in der Tat false

System.out.println(a==b); ist doch deswegen false da sie auf verschiedene Referenzen zeigen ?? Denk ich mir jedenfalls. Ach ja die equals Methode habe ich natürlich nicht überschrieben :rtfm:
 
Zuletzt bearbeitet:
Java:
package com.video2brain.java7.autos.fahrzeuge;

/**
 *
 * @author Michael Kulla (mkulla@gmx.de)
 */
public class Cabrio extends Auto {

    private boolean dachOffen;

    public Cabrio() {
        this("anonymes Cabrio");
    }

    public Cabrio(String name) {
        this(false, name);
    }

    public Cabrio(boolean dachOffen, String name) {
        super(name);
        this.dachOffen = dachOffen;
    }

    public void öffneDach() {
        if (!dachOffen) {
            System.out.println("Dach wird geöffnet.");
            dachOffen = true;
        }
    }

    public void schließeDach() {
        if (dachOffen) {
            System.out.println("Dach wird geschlossen.");
        }
        dachOffen = false;
    }

    @Override
    public String toString() {
        return super.toString() + " und das DAch ist " + (dachOffen ? "offen" : "geschlossen");
    }
}

package com.video2brain.java7.autos;

import com.video2brain.java7.autos.fahrzeuge.Auto;
import com.video2brain.java7.autos.fahrzeuge.Cabrio;

/**
 *
 * @author admin
 */
public class Typen {
    
    public static void main(String[] args) {
        
        Cabrio a = new Cabrio("abc"); 
        Cabrio b = new Cabrio("abc");
        
        System.out.println(a.equals(b));  // sollte doch true sein ?
        System.out.println(a==b);         // ist false und mir auch klar warum

sry wollte nicht so großen Text Blöcke spammen ... da kriegt man in anderen Foren immer eine auf den Decken. Schätze hier in den programmier Foren wird man da nachsichtiger sein 😀
 
Java:
package com.video2brain.java7.autos.fahrzeuge;

public class Auto {

    private int geschwindigkeit;
    private String name;

    public Auto(int geschwindigkeit, String name) {
        this.geschwindigkeit = geschwindigkeit;
        this.name = name;
    }
    
    public Auto(String name) {
        this(0, name);
    }

    public Auto() {
        this("anonym");
    }
    
    public void beschleunigen() {
        geschwindigkeit = geschwindigkeit + 1;
    }

    public void bremsen() {
        geschwindigkeit = geschwindigkeit - 1;
        if (geschwindigkeit < 0) {
            geschwindigkeit = 0;
        }
    }
    
    public void anhalten() {
        while (geschwindigkeit > 0) {
            bremsen();
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public int getGeschwindigkeit() {
        return geschwindigkeit;
    }
    @Override
    public String toString() {
        return name + " fährt gerade " + geschwindigkeit + " km/h";
    }
    
    public void hupen(int anzahl) {
        for (int i = 0; i < anzahl; i++) {
            System.out.print("Hup ");
        }
        System.out.println();
    }
}

uffa dachte ich bin so blöd weil es mir komisch vorkam. Anscheinend ist es das auch 😉
 
Wenn du zwei Objekte erzeugst, sind das zwei verschiedene Objekte. Sie sind zwar identisch, aber nicht ein und das selbe Objekt.
Deshalb kannst du auch nicht mit == überprüfen, denn das wird immer false liefern, außer du machst sowas:
Java:
Cabrio a = new Cabrio("abc");
Cabrio b = a;
System.out.println(a == b); // true

Die Methode equals aus der Klasse Object gibt einfach nur [c]this == other[/c] zurück, also ist bei Klassen, die equals nicht überschreiben, von Bedeutung, welche Referenz sie haben.
Du müsstest also die equals-Methode überschreiben. Eclipse hat da ein nettes Feature, welches automatisch equals-Methoden implementiert.
 
Du kannst ja mal testweise die toString()-Methode auskommentieren und dann beide Autos nochmal auf der Konsole ausgeben lassen. Dann siehst du, dass die Autos unterschiedlich referenziert werden im Speicher.
 
Mujahiddin hat gesagt.:
Sie sind zwar identisch, aber nicht ein und das selbe Objekt.
Sie sind zwar gleich, aber nicht ein und das selbe Objekt.
Ein kleiner aber feiner Unterschied 🙂

@TO:
Du musst in Auto equals überschreiben und die Attribute die du vergleich willst dort prüfen. Falls du keine Ahnung hast wie man die equals Methode implementieren muss, dann schau dir dazu auf jedenfall ein paar Beispiele an, das ist nicht trivial.
 
Bei Objekten ist also ist (a==b) das gleiche wie (a.equals(b)) ... aha verstanden.

Komischerweise funktioniert es bei Strings ... jedenfalls bei mir.

Dachte das equals den Wert der in der Speicherzelle geschrieben ist vergleicht... so wie bei String ... 😳
 
Zuletzt bearbeitet:
Bei Objekten ist also ist (a==b) das gleiche wie (a.equals(b)) ... aha verstanden.
Nene, das ist ganz falsch!
Wenn deine Klasse equals nicht überschreibt, dann greift die Implementierung von Object, und die vergleicht simpel per == (was soll die auch sonst machen?
In der Regel überschreibt ne Klasse aber die equals Methode, wie String bspw. auch.
 
ihr redet von Überladung oder ? Das Methoden vor allem die implementiert sind so schlau sind und alles fressen können und das wenn ich Strings mit equals vergleiche equals anderes funktioniert als wenn ich Objekte vergleiche ?
 
Nein, nicht Überladung.
Jede Klasse erbt von Object.
Object hat die equals Implementierung
Code:
return this == other;
Wenn deine Klasse von einer anderen Klasse erbt, dann wird jedes Mal, wenn auf ein Objekt deiner Klasse equals aufgerufen wird, die Hierarchie nach oben abgetastet, bis eine Klasse gefunden wird, die equals überschreibt. In deinem Fall ist das Object. Bei String ist das String (also die Klasse selbst.)
Du kannst aber equals überschreiben. Somit wird nicht mehr die Methode von oben (Object) genommen, sondern deine eigene Methode.
Du kannst dir ja mal String#equals ansehen.
 
Der Vergleich wir mit der Methode Equals durchgeführt. Wenn diese nicht den Anforderungen angepasst ist, vergleicht sie einfach die Adresse (also die Referenzen) der Objekte und die sind nicht gleich. Du musst nur die Methode equals so anpassen, dass sie den Vergleich macht und dann mit True oder False antwortet.

Pentalon
 
Nein, nicht Überladung.
Jede Klasse erbt von Object.
Object hat die equals Implementierung
Code:
return this == other;
Wenn deine Klasse von einer anderen Klasse erbt, dann wird jedes Mal, wenn auf ein Objekt deiner Klasse equals aufgerufen wird, die Hierarchie nach oben abgetastet, bis eine Klasse gefunden wird, die equals überschreibt. In deinem Fall ist das Object. Bei String ist das String (also die Klasse selbst.)
Du kannst aber equals überschreiben. Somit wird nicht mehr die Methode von oben (Object) genommen, sondern deine eigene Methode.
Du kannst dir ja mal String#equals ansehen.

okay jetzt hab ichs glaub ich gecheckt. Objekt ist die Basisklassen aller Klassen das oberste und dort drin ist equals mit return this == other ausgeführt.

okay wenn ich die Dokumentation sieht man das für Strings das Ding anderes funktioniert wie für Objekte ... auch wenn ihr es anderes ausdrücken würdest ... :rtfm:

public boolean equals(Object anObject)
Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
Overrides:
equals in class Object
Parameters:
anObject - The object to compare this String against
Returns:
true if the given object represents a String equivalent to this string, false otherwise


public boolean equals(Object obj)
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null object references:
...
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.

Parameters:
obj - the reference object with which to compare.
Returns:
true if this object is the same as the obj argument; false otherwise.
 
Zuletzt bearbeitet:
Du müsstest nur z.B. in Deiner Klasse Auto, eine Methode equals machen.

Java:
    public boolean equals(Auto that) {
        	return this.name == that.name;    		
    }
    
    public static void main(String[] args) {
    
    	Auto Auto1 = new Auto("Golf");
    	Auto Auto2 = new Auto("Golf");
    	
    	System.out.println("Vergleichen der Autos ergibt "+Auto1.equals(Auto2));
    } 
}

Damit legst Du fest, wie der Vergleich zu erfolgen hat und dann kommt auch das erwartete TRUE 🙂

Pentalon
 
Zuletzt bearbeitet:
Du müsstest nur z.B. in Deiner Klasse Auto, eine Methode equals machen.

Java:
    public boolean equals(Auto that) {
        	return this.name == that.name;    		
    }
    
    public static void main(String[] args) {
    
    	Auto Auto1 = new Auto("Golf");
    	Auto Auto2 = new Auto("Golf");
    	
    	System.out.println("Vergleichen der Autos ergibt "+Auto1.equals(Auto2));
    } 
}

Damit legst Du fest, wie der Vergleich zu erfolgen hat und dann kommt auch das erwartete TRUE 🙂

Pentalon

Falsch.
eher mit
Code:
return this.name.equals(other/*that klingt komisch*/.name);
 
Außerdem sind equals-Methoden i.d.R. etwas komplexer. Sie behandeln null und testen auf gleiche Klasse, bevor sie die EMember vergleichen.

Wer equals überschreibt, sollte auch hashCode überschreiben.

IDEs wie etwa Eclipse können beides erledigen.
 
Alles klar...

So ungefähr 🙂

Java:
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Auto other = (Auto) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

Danke liebes Eclipse....

Ob dass hier leichter zu verstehen ist, als der 3-Zeiler der natürlich nicht ganz korrekt war, sei mal dahingestellt.

Pentalon
 
Zuletzt bearbeitet:
Java:
public boolean equals(Auto other) {
            return (other != null && this.name.equals(other.name));          
    }

Es muss Object sein (wie bygones bereits sagte).

So was (Eclipse-generiert):
Java:
@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
	return result;
}

@Override
public boolean equals(Object obj) {
	if( this == obj )
		return true;
	if( obj == null )
		return false;
	if( !( obj instanceof Auto ) )
		return false;
	Auto other = (Auto) obj;
	if( name == null ) {
		if( other.name != null )
			return false;
	} else if( !name.equals( other.name ) )
		return false;
	return true;
}
 
Wer equals überschreibt, sollte auch hashCode überschreiben.

Ne, wenn hashCode() nicht benötigt wird, sollte und muss man es nicht überschreiben. Wenn es benötigt wird, sollte man es konform zu equals() überschreiben

@Mujahiddin: Irgendwie scheint es so, als wolltet ihr eine Wissenschaft draus machen 😀
 
Zuletzt bearbeitet von einem Moderator:
Ne, wenn hashCode() nicht benötigt wird, sollte und muss man es nicht überschreiben. Wenn es benötigt wird, sollte man es konform zu equals() überschreiben

@Mujahiddin: Irgendwie scheint es so, als wolltet ihr eine Wissenschaft draus machen 😀

Naja, sicherheitshalber sollte man wirklich beides überschreiben. Klar, hashCode() wird nicht überall gebraucht, wo equals() gebraucht wird, aber 1. macht das Eclipse sowieso automatisch und 2. geht man so auf Nummer Sicher. Später entscheidet man sich, ne HashMap zu verwenden und fragt sich, warum Objekte darin nicht mehr gefunden werden.
 

Zurück
Oben