Java 7 Grundkurs

Objekte erzeugen und initialisieren: der Konstruktor

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Mit Konstruktoren können Sie Objekte erzeugen und initialisieren. Mehr zu Speicherplatz reservieren, Klassen und Strings, die Sie bei der Arbeit mit Konstruktoren auch verstehen müssen.
13:39

Transkript

In diesem Video sehen Sie, wie Sie mit Konstruktoren Objekte erzeugen und initialisieren können. Das Beispielprojekt enthält eine Klasse "Auto". Dieses Auto hat zwei Attribute, nämlich Geschwindigkeit und Name. Die Geschwindigkeit lässt sich mit Beschleunigen und Bremsen beeinflussen, der Name lässt sich mit "getName" auslesen, mit "setName" ändern. Die Geschwindigkeit lässt sich natürlich auch auslesen, nämlich mit "getGeschwindigkeit". Außerdem hat das Auto noch eine Methode "getStatus", die ein kurze Statusmeldung zurückgibt, in diesem Falle also: Der Name des Autos, dann "fährt gerade", die Geschwindigkeit des Autos und "km/h". Diese Methode vereinfacht die Ausgabe von Statusmeldungen. In unserer Hauptklasse bauen wir uns dann ein Auto, geben ihm den Namen "Anna", beschleunigen ein bisschen und geben den Status aus, bremsen kurz und geben noch mal den Status aus. Bauen ein zweites Auto, geben ihm den Namen "Bernhard", dann beschleunigen wir ein bisschen mehr und geben den Status des zweiten Fahrzeugs aus. Wenn ich das Programm starte, sehen wir, das ist die Ausgabe: "Anna fährt 2", "Anna fährt 1 km/h", "Bernhard" fährt 3 km/h". Sind nicht so die schnellsten Autos halt. Dieses Programm hat einne kleinen Schönheitsfehler. Und zwar ist es möglich, ein Auto zu bauen, ohne ihm einen Namen zu geben. Ich zeige Ihnen das mal. Ich nehme diese Zeile hier mal heraus. D.h. ich baue einfach "meinAuto" und gebe dann den Status aus, ohne dem Auto vorher einen Namen gegeben zu haben. Wenn ich das ausführe, dann sehen wir hier: "null fährt gerade 2 km/h" und "null fährt gerade 1 km/h". Das ist natürlich sehr unschön und hat im Wesentlichen zwei Nachteile: Erstens, ist "null" kein besonders hübscher Name, und zweitens kann ich auf diese Weise mehrere Autos nicht mehr voneinander unterscheiden, wenn ich mehrere Autos habe, die alle keinen Namen tragen. Die melden sich ja alle mit "null". Was wir also benötigen ist ein Mechanismus, der es erzwingt, dass ein Auto bei seiner Erzeugung gleich einen Namen bekommt. Also etwa sowas hier. Ich habe hier die Erzeugung meines neuen Autos. Ich sage ja "new Auto", d.h. baue mir nach dem Bauplan "Auto" ein neues Auto und möchte hier gern den Namen übergeben können, als Parameter. Jetzt bekomme ich natürlich einen Compiler-Fehler, weil so, ohne Weiteres geht das natürlich nicht. Dazu müssen wir eine kleine Änderung an unserer Auto-Klasse vornehmen. Was hier fehlt, ist nämlich ein Konstruktor. Ein Konstruktor ist eine spezielle Art von Methode, die dazu da ist, ein Objekt zu konstruieren und zu initialisieren. Ein Konstruktor hat zwei wesentliche Eigenschaften. Zuerst einmal heißt er genauso wie die Klasse, d.h. wenn die Klasse "Auto" heißt, heißt auch der Konstruktor "Auto". Und zum Zweiten gibt er nichts zurück, also nicht mal "void", aber er kann Parameter übernehmen. Achten Sie darauf, dass Sie "String" groß schreiben, sonst gibt es einen Compiler-Fehler. Ansonsten, wie gesagt, die Syntax genauso wie die einer normalen Methode, nur eben kein Rückgabetyp und Name genauso wie die Klasse. Im Konstruktor können wir jetzt den Namen entgegennehmen und per "this.name" greifen wir auf den Namen, auf das Attribut "name", von diesem Objekt zu und können den Wert des Parameters "Name" übergeben, "name" natürlich. So. Das ist unser Konstruktor. Der Konstruktor wird für jedes Objekt genau einmal aufgerufen, nämlich, wenn das Objekt erzeugt werden soll, und zwar hier. Wir sehen, die rote Linie ist jetzt verschwunden. Dafür ist hier unten eine neue rote Linie erschienen. Dazu kommen wir gleich. Also, "new" reserviert den entsprechenden Speicherplatz, der nötig ist, um das Objekt im Speicher anzulegen und dann ruft "new" den Konstruktor auf, der so aussieht, d.h. also den Konstruktor der Klasse "auto", der bereit ist, einen String entgegenzunehmen. Das ist genau der Konstruktor, den wir gerade beschrieben haben. Ohne dass wir etwas Spezielles dafür tun müssen, erzeugt nun dieser Konstruktor ein Auto-Objekt und belegt alle Attribute mit ihren Standardwerten. Und dann macht der Konstruktor noch das, was wir ihm zusätzlich hier reingeschrieben haben, in unserem Fall also, nachdem du alles mit Standardwerten belegt hast, nimm noch mal diesen Namen hier entgegen und setze den mal auf das Attribut "name". Dann ist der Konstruktor zu Ende und das Objekt ist fertig erzeugt. Wenn also irgendwelche Aktionen notwendig sind, um ein Objekt vollständig funktionsfähig zu machen, irgendwelche Initialisierungen, dann schreiben Sie die in einen Konstruktor hinein. Auf diese Weise ist abgesichert, dass, wenn das Objekt vollständig erzeugt wurde, es auch tatsächlich einsatzbereit ist. Unsere Klasse hat nun genau einen Konstruktor, nämlich diesen hier, und dieser Konstruktor erwartet einen String. In unserer Mengenmethode rufen wir hier unten aber einen Konstruktor auf, der keinen String bekommt, d.h. hier gibt es einen Compiler-Fehler. Wir sehen also, wir haben tatsächlich abgesichert, dass wir jetzt kein Auto mehr erzeugen können, ohne einen Namen zu übergeben. Ich ändere das hier unten jetzt mal ab. Ich übergebe jetzt hier den Namen. So, "Bernhard". Dann kann ich das "setName" weglassen. Strg+E, und nun ist auch der zweite Fehler wieder verschwunden. "Programm ausführen" zeigt, es läuft alles immer noch genauso wie es soll. Der Unterschied zu vorher ist, dass es jetzt nicht mehr möglich ist, aus Versehen oder vorsätzlich ein Auto zu bauen, das keinen Namen bekommt und, dass Sie, um ein Auto mit einem Namen zu erzeugen, nicht mehr extra noch die Methode "setName" aufrufen müssen. Wenn Sie aufgepasst haben, haben Sie sicher bemerkt, dass wir auch schon Objekte erzeugen konnten, bevor wir wussten, was ein Konstruktor ist und bevor wir einen schreiben mussten. Hier hat uns nämlich der Java-Compiler ein wenig unter die Arme gegriffen. Wenn wir gar keinen Konstruktor in unsere Klasse hineinschreiben, dann erzeugt uns der Compiler automatisch einen sog. Standardkonstruktor. Der sieht so aus, der heißt natürlich genauso wie die Klasse, klar. Er nimmt keine Parameter und auch ansonsten enthält er eigentlich nicht wirklich etwas. Das ist der Standardkonstruktor. Den erzeugt Ihnen der Compiler automatisch, wenn Sie gar keinen Konstruktor in Ihre Klasse hineinschreiben. Auf diese Weise ist abgesichert, dass von jeder Klasse auch immer Objekte erzeugt werden können, egal, ob der Entwickler einen Konstruktor vorgesehen hat oder nicht. Schreiben Sie selbst aber einen Konstruktor hinein, also das was wir eben hatten, so, dann sieht der Compiler keine Notwendigkeit, seine Hilfeleistung anzubringen und Sie bekommen nur den Konstruktor, den Sie tatsächlich selbst hineingeschrieben haben. Also, schreiben Sie gar keinen Konstruktor rein, kriegen Sie automatisch einen geschenkt, und zwar den, der nichts tut, außer ein Objekt zu erzeugen. Schreiben Sie selbst einen Konstruktor hinein, dann haben Sie nur den, den Sie selbst reingeschrieben haben. Sie müssen sich jetzt allerdings nicht entscheiden, ob sie jetzt den mit den ohne ohne Parameter haben wollen, denn Sie können problemlos auch beide Konstruktoren einbauen. Zum Erzeugen von Konstruktoren gibt es natürlich wieder eine enorme Vereinfachung, wenn Sie eine IDE haben. Ich drücke hier Alt+Einfg, und bekomme wieder mein kleines Mini-Menü. Der erste Punkt heißt "Constructor". Jetzt kann ich sagen, welche Parameter der Konstruktor übernehmen soll und an Attribute weitergeben soll. Wir wollen den Standardkonstruktor haben, den "Default Constructor", wir wollen also keine Parameter übernehmen, lassen also alles weg, und drücken einfach nur auf "generate", und dann bekommen wir den leeren, minimalen Standarkonstruktor dazu generiert. So, jetzt haben wir beide Konstruktoren. Das ist zwar eigentlich nicht das, was wir wollen. Ich mache das aber hier einfach mal, um zu demonstrieren, dass es möglich ist. Zwei Konstruktoren können Sie haben, wenn Sie zwei verschiedene Parameterlisten für die Konstruktoren haben. Dann ist das für den Compiler vollkommen in Ordnung. Der eine Konstruktor nimmt keinen Parameter und der andere nimmt einen Parameter, d.h. wenn Sie jetzt irgendwann mal ein Auto erzeugen, das einen String nimmt, dann wird dieser Konstruktor verwendet, bauen Sie ein Auto, das gar keinen Parameter nimmt, dann wird dieser Konstruktor verwendet. Es kann durchaus sinnvoll sein, das in der Praxis tatsächlich so zu handhaben, dass wir einen Konstruktor haben, der Parameter nimmt und die Attribute setzt, und einen Konstruktor, der keine Parameter nimmt. Dieser setzt dann typischerweise Default-Attribute. Das heißt also, sowas z.B., das ermöglicht jetzt den anderen Entwicklern, die Ihre Klasse benutzen möchten, Ihre Auto-Klasse, dass Sie entweder den Default-Konstruktor benutzen möchten, wenn Sie nicht so richtig wissen, welche Parameter Sie da übergeben wollen, oder Sie benutzen den Konstruktor, der Parameter nimmt und dann können Sie die Parameter auch entsprechend übergeben. Das ist natürlich immer nur dann sinnvoll, wenn es auch wirklich in der Anwendung so gedacht ist und wenn die Anwendung das auch wirklich so möchte. In unserem Fall haben wir noch ein weiteres Attribut, nämlich "Geschwindigkeit". Es wäre also durchaus denkbar, dass wir einen dritten Konstruktor haben möchten, der sowohl Name als auch Geschwindigkeit übernimmt, um ein Auto bauen zu können, was gleich von vorneherein eine andere Geschwindigkeit als "null" hat. Also, Alt+Einfg, "Constructor", jetzt setzen wir zwei Häkchen, eins für "Geschwindigkeit", eins für "Name" und drücken auf "generate", dann haben wir einen Konstruktor, der genau das tut: zwei Parameter nehmen und die Attribute auf die Werte setzen. Die Parameter sind einfach durch ein Komma getrennt und die Werte, die hier hereinkommen, werden an die Attribute weitergegeben. Wenn wir uns das jetzt so anschauen, dann stellen wir fest, wir haben hier schon wieder Code mehrfach. Wir haben hier stehen "this.name = name" und hier stehen "this.name = name" und hier haben wir "this.name = " naja, Standardname sozusagen. Da eine solche Situation in der Praxis recht häufig vorkommt, gibt es dafür auch eine erprobte Lösung und die nennt sich "Constructor Chaining" oder "Konstruktoren-Verkettung". Das sieht dann folgendermaßen aus: Sie bauen sich einen Konstruktor, der alle Parameter nimmt, d. h. also die längste Liste hat. In diesen Konstruktor schreiben Sie Ihre vollständige Initialisierung hinein, also testen, ob die Werte korrekt sind, setzen der Werte usw. Die anderen Konstruktoren, die leiten dann nur an diesen Kontruktor weiter, statt selbst die Initialisierung auch wieder noch mal zu übernehmen. Das sieht folgendermaßen aus: Wir verwenden hier wieder das Schlüsselwort "this", nur diesmal mit runden Klammern dahinter. Dieser Konstruktor bekommt einen Namen übergeben, aber keine Geschwindigkeit, deswegen macht er Folgendes: Er möchte jetzt den Konstruktor dort oben aufrufen, der möchte als Erstes die Geschwindigkeit, als Zweites den Namen. Also, schreiben wir hier hin "this(0, name);". Das bedeutet, wenn jemand diesen Konstruktor aufruft, indem er, so wie wir das hier machen, sagt "newAuto Anna", dann ist das der Konstruktor hier, der ruft per "this()" einen anderen Konstruktor auf und zwar einen, der eine Zahl nimmt und einen String. Das ist dieser hier. Der übergibt als Zahl die Null, als Startgeschwindigkeit quasi, und als Name übergibt er den Namen, der hier reingekommen ist. Das Gleiche können wir jetzt hier unten mit unserem Standardkonstruktor auch noch machen. So. Der Konstruktor ohne Parameter sagt jetzt einfach: Setzen wir den Namen defaultmäßig auf "anonym". Mehr macht der nicht, d.h. also jetzt wird dieser Konstruktor aufgerufen, nimmt den Namen "anonym" entgegen, fügt die Geschwindigkeit "0" hinzu und ruft dadurch den dritten Konstruktor auf. Dieser Konstruktor übernimmt nun die eigentliche Initialisierung des Objektes, mit, in unserem Fall, wenn wir von hier gekommen sind, den Standardwerten "0" und "anonym". Wir sind nun völlig frei darin, mit welchem Konstruktor wir unser Objekt erzeugen möchten. Wir können gar keinen Parameter angeben, wir können den Namen angeben oder wir können Namen und Geschwindigkeit angeben. Für alle Varianten gibt es eine Lösung und der Entwickler dieser Klasse "Auto" muss die eigentliche Initialisierung nur ein einziges Mal vornehmen. Insbesondere, wenn Sie längere Parameterlisten haben oder wenn die Parameter noch getestet werden müssen, ob sie gültig sind, ob sie sich innerhalb eines zulässigen Bereiches befinden usw. dann ist das durchaus eine sehr vorteilhafte Art und Weise, weil Sie nämlich alles an einer Stelle haben, nämlich hier oben, in diesem Konstruktor und die anderen Konstruktoren lediglich an diesen weiterleiten müssen. So nun habe ich Ihnen sehr viel über Objekterzeugung und Initialisierung erzählt. Wer kümmert sich nun aber eigentlich um das Aufräumen, d.h. also das Entsorgen der Objekte, wenn sie nicht mehr gebraucht werden? Glücklicherweise gibt es dafür bereits einen Dienst, der fleißig im Hintergrund werkelt, und das ist der sog. "Garbage Collector", der "Müllsammler". Der kümmert sich im Hintergrund darum, den Speicher aufzuräumen, Objekte, die nicht mehr zugegriffen werden können, freizugeben und entlastet so Sie, den Entwickler, davon, sich selbst darum kümmern zu müssen. Solange Sie in Ihrem Programm noch irgendwo eine Variable haben, mit der Sie an ein Objekt rankommen können, solange lässt der "Garbage Collector" das Objekt auch in Ruhe. Wenn Sie keine Variable mehr haben, mit der Sie an das Objekt rankommen, wenn das Objekt für Sie also aus keinem Teil des Programms mehr erreichbar ist, dann ist das Objekt bereit für den "Garbage Collector" und er kümmert sich darum, das Objekt freizugeben und den Speicher freizugeben. So, damit haben Sie nun gesehen, wie Sie mit Konstruktoren Objekte erzeugen können, wie Sie mehrere Konstruktoren anlegen können, die sich gegenseitig aufrufen, wie Sie die Initialisierung Ihrer Objekte von den Konstruktoren erledigen lassen können und schließlich haben Sie auch erfahren, dass es einen "Garbage Collector" gibt, der sich um das Aufräumen des Speichers kümmert und der die Objekte freigibt, die Sie nicht mehr benutzen möchten.

Java 7 Grundkurs

Machen Sie sich mit den Grundlagen der Java-Programmierung vertraut und lernen Sie die Syntax der Sprache sowie das Konzept der objektorientierten Softwareentwicklung kennen.

8 Std. 32 min (66 Videos)
Derzeit sind keine Feedbacks vorhanden...

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!