Java "static" nicht verstanden und Programm funktioniert (noch) nicht

Uuuuuuuund nochmal. :D

Ich hab jetzt nochmal die equals-Methode verändert. Jetzt müsste sie eigentlich korrekt sein. Stimmt das?
Muss ich bei "4. Paarweisen Vergleich" das für jedes getXXX machen? Oder wie ist das mit den Objektvariablen gemeint?

Danke nochmal! :)



Code:
public class Person{
	String name;
	int alter;
	
	public Person(String name, int alter){
		this.name = name;
		this.alter = alter;
	}
	
	public void setName(String name){
		this.name = name;
	}
	
	public void setAlter(int alter){
		this.alter = alter;
	}
	
	public String getName(){
		return name;
	}
	
	public int getAlter(){
		return alter;
	}
		
	public String toString(){
		return "Name: " + this.name + "\nAlter: " + this.alter;
	}
	
	/*
	public boolean equals(Person obj){
		if(this.name == obj.getName() && this.alter == obj.getAlter()) return true;
		return false;
	}
	*/
	
	public boolean equals(Object obj){
		// 1.) Vergleich mit null
		if(obj == null)
    	return false;

		// 2.) Test auf selben Typ
		if(getClass() != obj.getClass())
    	return false;

		// 3.) Gleiche Basisklassenobjekte
		if(!super.equals(obj))
    	return false;

		// 4.) Paarweiser Vergleich der Objektvariablen
		Person that = (Person)obj;
		if(getName() != that.getName())
    	return false;

		return true;
	}
}
 
Code:
public boolean equals(Object obj) {
     return (obj instanceof Person) && (name.equals((Person)obj).name);
}

Ist etwas kürzer ;)

Deine zweite Frage versteh ich leider nicht :(

// edit
Jetzt hab ich kapiert, was du meinst!
Nun, es ist allein deine Entscheidung, ab wann du sagst, dass zwei Personen identisch sind.
Wenn du sagst, der Name allein reicht dir, dann genügt meine Implementation. Falls du sagst, eine Person ist nur dann gleich einer anderen Person, wenn sowohl Name wie auch Alter übereinstimmen, musst du natürlich auch die anderen Attribute vergleichen!
 
Zuletzt bearbeitet:
Danke. :)

Ich werde dann bei der equals-Methode alle sinnvollen Variablen vergleichen. Also z. B. Name UND Alter statt nur Name.

Jetzt hab ich noch ne kurze Frage:

Code:
public boolean equals(PKW pkw)
Code:
public boolean equals(Object obj)
Die Klasse heißt "PKW".

Was ist der Unterschied?

statt pkw würde ich halt dann obj nehmen. Das ist nur eine Variable und daher kann man das so lassen. Stimmt das?
Aber was ist der Unterschied zwischen "PKW" und "Object"?




//
2. Frage:


Code:
"\nMarke: " + getMarke() +
Code:
"\nMarke: " + this.marke +

Die zwei Zeilen sind gleichwertig, oder?
Also kann man beide in der toString-Methode verwenden?




//
3. Frage:

Welcher Code von beiden ist besser?

Code:
	public boolean equals(PKW pkw)
	{
		if(this.automarke == pkw.getAutomarke() && this.kennzeichen == pkw.getKennzeichen() && this.sitzplaetze == pkw.getSitzplaetze())
		{
			return true;
		}
		return false;
	}

Code:
	public boolean equals(Object obj){
		if(obj == null) return false;
		
		if(getClass() != obj.getClass()) return false;
		
		if(!super.equals(obj)) return false;
		
		PKW that = (PKW)obj;
		
		if(
		getKennzeichen() != that.getKennzeichen() &&
		getAnzahlDerSitzplaetze() != that.getAnzahlDerSitzplaetze() &&
		getFahrzeugNummer() != that.getFahrzeugNummer() &&
		getMarke() != that.getMarke()
		) return false;
		
		return true;
	}



//
Noch eine ... :(
4.

Code:
	public void print(){
		for(String i : liste) if(i != null) System.out.println(i);
	}

Code:
	public void print(){
		for(String i : liste) System.out.println(i);
	}

Gibt der undere Code auch die leeren Elemente des Arrays aus (also leere Zeilen)?
 
Zuletzt bearbeitet:
Frage 1:
Der Unterschied ist groß und bedeutend. Wenn du equals(Object) implementierst, überschreibst du damit die Methode der Basisklasse Object (bzw. der Eltern in der Klassenhierarchie). Tust du das, solltest du unbedingt (auch um den Unterschied sichtbarer zu machen) die (leider optionale) Annotation @Override darüber platzieren. Eine IDE wie Eclipse hilft bei sowas automatisch, wenn man sie richtig benutzt. Gibt da verschiedene Wege.

Grundsätzlich würde ich davon abraten equals mit einer anderen Signatur zu überladen. Das verwirrt dich und andere, die mit deinem Code zu tun haben und ist sehr fehleranfällig.

Frage 2:
Solange die getter-Methode keine Seiteneffekte hat, ist das gleichwertig in der toString zu verwenden, ja. Wenn dir aber später mal einfällt, dass bei jedem get etwas zusätzliches passieren soll (d.h. du machst in dem getter irgendwelche tollen Dinge), dann würde an dieser Stelle, wo du nicht den getter verwendest sondern direkt an das Feld bindest, dieser zusätzliche Effekt nicht passieren. Man ist also flexibler, wenn man durchgängig den getter verwendet.

Frage 3:
​Siehe Antwort auf Frage 1.
 
Hi,

ich zitiere mal kurz die Angabe zur Aufgabe:

Redefinieren Sie darüber hinaus in der Klasse PKW die drei Methoden
1. boolean equals(Objekt obj)
2. String toString()
3. public in hashCode()

Ich überschreibe (= redefiniere?) die Methode also nicht, weil ich es gut finde, sondern weil der Prof. das gerne so hätte. Die Prüfung ist auf Papier. :)

Meiner Ansicht nach, mmuss ich sogar mit "(Object obj)" arbeiten, da ich genau diese laut Aufgabe verwenden soll.
Die Version mit "(PKW pkw)" ist von den Tutoren.

Soll ich @Overrride vor die Methode schreiben, um beim Prof. einen besonders guten Eindruck zu erwecken? :D


Frage 2: Dann passt das.

Danke :)
 
Zuletzt bearbeitet:
Es gibt überschreiben (override) und überladen (overload). Gleichzeitig kannst du auch überladene Methoden überschreiben. :)

Überschreibst du eine Methode, gibst du ihr eine alternative Implementierung, behältst aber die Signatur bei. Überlädst du eine Methode, erstellst du eine weitere Variante einer bereits existierenden Methode, die sich durch die Signatur unterscheidet.
Das Problem hierbei ist, dass anderer Code wie z.B. die Java-eigenen Klassen (Set, Map, usw.) die "echte" benutzen, d.h. die mit Object als einzigem Parameter. Deine wird von denen ignoriert. Gerade für diese Klassen ist es aber enorm wichtig, dass equals und hashCode korrekt implementiert sind, sonst treten lustige Fehler auf, die viel Zeit kosten beim Debuggen.

Beim Überschreiben bitte @Override drüberklatschen. An sowas denk ich schon gar nicht mehr, weil es wie gesagt normalerweise automatisch passiert, es sei denn du schreibst den Code auf Papier oder in einem simplen Editor. Du teilst damit dem Compiler mit, dass deine Absicht ist zu überschreiben, nicht zu überladen. Dadurch kann er dich warnen, wenn deine Signatur abweicht vom Original.
 
Zuletzt bearbeitet:
Danke. :)

Jetzt ist mir glaub ich ein Fehler im Lösungsvorschlag der Tutoren aufgefallen (es geht um eine andere Aufgabe):

Code:
	public String[] sort(){
		String[] sortiert = this.liste;
		Arrays.sort(liste);
		return sortiert;
Sollte Zeile 3 nicht sinnvollerweise Arrays.sort(sortiert) lauten?
Angabe: "... gibt eine aufsteigend sortierte Kopie(!) der Gästeliste als String-Array zurück"
Return würde meiner Ansicht nach dann fälschlicherweise zwar eine Kopie von liste zurückgeben, welche aber dann nicht sortiert ist.

Prüfung auf Papier: ja
Editor: Notepad++ :D
 
@Frage 4:
Leere Strings werden als letzten Zeile geprinted, ja.
 
Zuletzt bearbeitet:
Danke. Dann man ich da einfach die if-Abfrage mit != null rein.
 
Das prüft nicht ob der String ein leerer String ist. Dafür würde sich sowas wie isEmpty anbieten.

Wenn ein string aber null sein kann musst du das natürlich auch noch prüfen.
 
Ups, dann hab ich nen Denkfehler.

Wie ist das, wenn ich z. B. ein Array mit 200 Elementen hab. Nach und nach werden dann 100 davon beschrieben.
Sind die restlichen dann "null" oder "empty"?
 
Null. Empty wäre einfach ein String Objekt ohne Zeichen. String s = "";
 
Zuletzt bearbeitet:
Dann wäre:

for(String i : liste){
if(i != null) System.out.println(i);
}

richtig bzw. sinnvoll, wenn man nicht 100 leere Zeilen haben möchte?
 
Was meinst du mit leeren Zeilen? :P System.out.println("") ist auch ne leere Zeile =)
Bei

String s = null;
System.out.println(s);

kommt übrigens "null" als Ausgabe raus =)
Wenn du alle unbeschriebenen Strings (die 100 Elemente) nicht ausgeben willst passt das. Wenn du keine leeren Zeilen ausgeben willst musst du if(i != null && !i.isEmpty()) abfragen.


Der Lösungsvorschlag deiner Tutoren funktioniert übrigens, da das eine nur eine Referenz auf das andere ist. Sieht aber extrem schlecht aus und war wahrscheinlich nicht so gewollt.
 
Zuletzt bearbeitet:
Zu den Arrays.sort:
Ganz kann ich leider deine Antwort nicht nachvollziehen.

Code:
    public String[] sort(){
    String[] sortiert = this.liste;
    Arrays.sort(liste);
    return sortiert;

2. Zeile: das Array "sortiert" soll aus dem Array "liste" bestehen (also eine Zuweisung, wie z. B. a = b)
3. Array "liste" soll sortiert werden
4. Array "sortiert" wird zurückgeben
"sortiert" wurde aber bei 3. nicht sortiert, sondern "liste" wurde sortiert. (Variablenname ist in dem Beispiel etwas unglücklich gewählt.)


Für mich klingt das wie:

b = a;
sort (a);
print b;

Oder meinst du, das ist ein "Call by reference" und kein "Call by value"? Aber ist das dann noch eine Kopie?
 
​Da wird keine Kopie erzeugt. Deswegen muss man bei veränderbaren Objekten und Arrays ganz besonders aufpassen.

Am besten findest du solche Dinge aber raus, indem du einfach probierst.

Code:
public class ArraySort {


    String[] liste = new String[] { "lu", "le", "la" };


    public String[] sort() {
        final String[] sortiert = this.liste;
        Arrays.sort(liste);
        System.out.println("hash of liste:" + liste);
        System.out.println("hash of sortiert:" + sortiert);
        return sortiert;
    }

    public static void main(final String[] args) {
        final ArraySort arraySort = new ArraySort();
        final String[] arrayReturnedFromSort = arraySort.sort();
        System.out.println("hash of arrayReturnedFromSort:" + arrayReturnedFromSort);
        System.out.println("Returned array: " + Arrays.toString(arrayReturnedFromSort));
    }
}
output:
Code:
hash of liste:[Ljava.lang.String;@2f3cf887
hash of sortiert:[Ljava.lang.String;@2f3cf887
hash of arrayReturnedFromSort:[Ljava.lang.String;@2f3cf887
Returned array: [la, le, lu]

Tut doch gar nicht weh oder? :)
 
Danke Leute. :)

Seit heute steht die Note online. 1.0 :D
 
Wir hätten dich auch gehauen, wenn das nicht rausgekommen wäre.
Herzlichen Glückwunsch! :schluck:
 
Zurück
Oben