Frage von Docenock, 81

Warum wird bei Java die Variable "doppelt" eingeführt?

Hallo, ich habe mal eine kleine Frage zu Java bin noch relativ am Anfang aber möchte es gerne so gründlich wie möglich verstehen da ich darüber eine Klausur schreibe! Mein Problem ist folgendes: Ich habe diesen Code:

class Dog extends Animal {

int age;
public Dog(int dogsAge) {
age = dogsAge;
 }

Der Code geht natürlich noch weiter aber meine Frage ist: Warum führe ich erst "age" ein um danach nochmal age=dogsAge zu setzen? Kann ich da nicht einfach direkt den int "age" weglassen? Denn wenn ich das Objekt erstelle benutze ich doch im Prinzip nur die Variable "dogsAge", die Variable "age" brauche ich doch garnicht, oder sehe ich das falsch? Das Bespiel entstammt der Seite codecademy.com, würde mich freuen wenn mir jemand das erläutern könnte :)

Liebe Grüße!

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von Suboptimierer, 54

dogsAge gibt es nur innerhalb von Dog().
age = dogsAge bewirkt, dass das Alter im Objekt gespeichert wird und später darauf zugegriffen werden kann.

Was mich allerdings irritiert ist, dass age nicht bereits bei Animal deklariert wurde, denn jedes Tier hat ein Alter.

Kommentar von Docenock ,

Danke! Ich glaube ich habe es verstanden!
Das Beispiel ist ein bisschen unglücklich denn die Klasse Animal existiert zu dem Zeitpunkt an dem ich das Beispiel rauskopiert habe noch nicht :D Man fängt mit der dog Klasse an und fügt dann die Animalklasse hinzu und schafft die Attribute die nicht Hundespezifisch sind dann erst rüber :D

Kommentar von Suboptimierer ,

Achso, gut, das wusste ich nicht. Im Rahmen dieser Lehrbeispiele ist ja fast alles erlaubt.

Antwort
von NoHumanBeing, 30

Ich würde, wenn ich auf Variablen des Objekts zugreife, grundsätzlich immer das Schlüsselwort "this" verwenden. Dann können lokale Variablen und Objektvariablen auch den gleichen Namen haben. Über "this" wird dann jeweils die Objektvariable angesprochen. Ansonsten "verdecken" lokale Variablen die Objektvariablen (shadowing).

Außerdem würde ich die Variable als "private" deklarieren. Außerdem könnte man sie hier, da sie nur im Konstruktor gesetzt wird und ansonsten nie wieder schreibend auf sie zugegriffen wird, sogar als "final" deklarieren.

class Dog extends Animal {
private final int age;

public Dog(int age) {
this.age = age;
}

public int getAge() {
return this.age;
}

}

Sobald Du Code hast, der das Alter verändert (das Alter verändert sich ja schon dadurch, dass Zeit verstreicht), musst Du das "final" entfernen.

Das Schlüsselwort "this" gibt Dir eine Referenz auf das aktuelle Objekt (auf das die Methode aufgerufen wurde). Lokale Variablen gleichen Namens "verdecken" Objektvariablen (shadowing).

Ich empfinde das "this" auch so (wenn kein shadowing stattfindet), als "guten Stil", sozusagen um noch einmal explizit hinzuschreiben, dass ich hier auf eine Objektvariable zugreife.

Wenn es nach mir ginge, könnte die Sprache den Zugriff auf Objektvariablen und Methoden ohne das Schlüsselwort "this" (oder allgemein eine Objektreferenz) verbieten. Leider ist dem aber nicht so. Ich programmiere trotzdem so, als wäre dem so. Empfinde ich als "guten Stil". Man muss nicht alles machen, was die Sprache einem erlaubt. Wenn man eine bestimmte Sache "expliziter" tun kann, als von der Sprache gefordert, ist es oft auch gut, dies zu tun, weil man damit aktiv dokumentiert, dass man wirklich genau dies möchte (z. B. eben auf das Objekt zugreifen).

Kommentar von KnusperPudding ,

Die Antwort ist in der Summe sehr ausführlich, mit ein paar mehr Details noch die ich nicht erwähnte. 

das mit dem Shadowing sehe ich prinzipiell ja schon ein. und age hier doppelt zu verwenden ebenso. Allerdings this an allen möglichen Stellen zu verwenden leuchtet mir jedoch nicht so ganz ein. - Bei Instanz-Variablen finde ich es bei der Leserlichkeit zwar auch besser, jedoch stünde diese Option dann auch noch für Methoden zu Verfügung - und da würde ich bei Methodenaufrufen eher auf ein this verzichten.

Kommentar von NoHumanBeing ,

Das stimmt. Bei Methoden gibt es im Prinzip keine Doppeldeutigkeit, daher wäre das "this" redundant. Aber es dient der Konsistenz. Wenn Du auf einem "fremden" Objekt eine Methode aufrufst, schreibst Du "objektreferenz.methode(...)". Für den Spezialfall, dass Du die Methode "auf Dir selbst" aufrufst, ist die Objektreferenz eben das Schlüsselwort "this".

Es bringt aber nichts, sich darüber zu streiten, deswegen werde ich das an dieser Stelle auch nicht tun. ;-)

Syntaktisch ist beides korrekt, das heißt dem Rechner ist es "egal". Es ist gewissermaßen persönliche Präferenz. Dereferenzieren muss die JVM bei Methodenaufrufen ohnehin, das heißt das "this." bewirkt keine zusätzliche Dereferenzierungsoperation, die Laufzeit kostet (auch wenn es zunächst so aussehen mag).

Kommentar von KnusperPudding ,

Mir ginge es nicht ums 'Streiten', nur manchmal verstehe ich andere 'Ansichten' nicht, bin aber froh wenn ich noch dazu lernen kann.

Kommentar von NoHumanBeing ,

Hatte es auch nicht als "Streit" interpretiert. Ich wollte nur sagen, ich werde jetzt nicht in eine Diskussion ausarten, ob man es so oder so machen sollte, denn es wird sehr wahrscheinlich darauf hinauslaufen, dass wir beide es weiterhin so machen werden, wie wir es bisher für richtig hielten und das ist ja auch in Ordnung so. ;-)

Expertenantwort
von KnusperPudding, Community-Experte für Java, 46

Bei dieser Zeile:

public Dog(int dogsAge) {

Handelt es sich um den Konstruktor, mit dem eine Instanz einer Klasse gebildet wird. - Dieser Instanz gibst du eine Zahl mit: dogsAge. - mit dem Aufruf des Konstruktors wird durch den Parameter dogsAge die Instanz-Variable: age befüllt.

Die Variable dogsAge hätte nur Gültigkeit innerhalb des Konstruktors, dadurch dass die Instanz-Variable age gesetzt wurde, kann dieser von überall innerhalb der Instanz verwendet werden.

In wie weit das 'Sinn' macht, hängt davon ab, wie dein restlicher Code aussieht. und in wie weit du die Variable noch weiter verwendest.

Kommentar von Docenock ,

Hey Danke schonmal!
Später greift das Programm nochmal auf die Variable zu auf diese Weise:

public int getAge() {
return age;

Wenn ich dich richtig verstanden habe könnte er garnicht auf dogsAge zugreifen, daher muss man age=dogsAge setzen, oder?
Vielen Dank :)

Kommentar von KnusperPudding ,

Das ist korrekt so! Absolut richtig erkannt.

Antwort
von Omnivore08, 10

Genau das ist der Punkt den du lernen sollst über objektorientiere Programmierung. Da finde ich C# besser, da man da Eigenschaften einer Klasse direkt speichern und ansprechen kann.

Bei Java werden klasseninterne Eigenschaften als 'private' deklariert und dann über getter- und setter-Funktionen angesprochen.

Die set-Funktion musst du dir Vorstellen wie ein Befehl, den du an den Hund gibst. Du sagst dem Hund also "du bist jetzt soviele jahre alt". Das "soviele" entspricht also deinem "dogsAge". Mit dieser Information setzt der Hund intern sein Alter.

Warum macht man das so und nicht anders? Nun...es gibt Situationen, da muss man etwas mehr machen als nur das Setzen. Oder es wird intern noch in Tage umgerechnet und nach aussen immer in Jahre. oder oder oder. Auf Klasseninterne Variablen sollte man direkt niemals zugreifen dürfen (rechte). Daher das bitte immer über getter- und setter-Funktionen kapseln

Ich hoffe ich konnte dir helfen

Gruß
Omni

Keine passende Antwort gefunden?

Fragen Sie die Community