Skip to main content

So kannst du Java Konstruktoren anlegen und überladen


Kon

Der Name sagt es schon.

Java Konstruktoren konstruieren oder bauen Java Objekte.
Und diese Objekte baut der Konstruktor auf Vorlage der entsprechenden Java Klasse.

In diesem Beitrag zeige ich dir natürlich verschiedene Ansätze wie du den Konstruktor einsetzt.
Ich zeige dir dies Schritt für Schritt.

Dabei zeige ich dir auch verschiedene Dinge, welche nicht funktionieren.
Ich zeige dir natürlich auch warum diese nicht funktionieren.

Ja warum so ausführlich?
Ich möchte, dass du ein besseres Verständnis im Umgang mit Konstruktoren aufbaust.

Einen Konstruktor rufst du immer durch das Keyword new auf.
Dein Java Programm bekommt dann den Befehl: „Jetzt muss ich ein Java Objekt bauen“

Danach folgt der Klassenname.
Dein Programm weiß dann: „Okay, ich soll nicht irgendein Objekt bauen.
Nein, ich soll ein Objekt aus dieser bestimmten Klasse bauen.“

Dann folgt immer die Parameterliste.
Dein Programm weiß dann auch: „Ah ja, diese Eigenschaften soll das Objekt von Anfang an haben.“

Und da du ein Objekt immer zum Programmstart brauchst, implementierst du den Konstruktor in die main Methode.

Das ganze sieht dann so aus.

Die Beispielklasse Tier:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert
}


Die Klasse Programmstart:

public class ProgrammStart{
public static void main (String [] args) {
Tier loewe = new Tier ();//Der Konstruktor legt ein neues Tierobjekt, namens loewe an.
}
}

Wenn wir jetzt so ein Tier (Löwen) erschaffen, braucht es Eigenschaften.

Und diese Eigenschaften müssen wir dem Tier zuweisen.
Der Konstruktor hat keine Parameter in seiner Parameterliste.
Das bedeutet, dass dieses Tier jetzt noch eigenschaftslos ist.

Das werden wir ändern.

Das ganze machst du über die Punktnotation.

  • Du nimmst den Namen deines Objektes.
  • Setzt einen Punkt.
  • Wählst dann die Eigenschaft bzw. Instanzvariable aus.
  • Und machst dann die Zuweisung.

Und so geht’s.

Zum Programmstart bekommt der Löwe eine Größe von 200 Zentimetern zugewiesen:

public class ProgrammStart{
public static void main (String [] args) {
Tier loewe = new Tier ();//Der Konstruktor legt ein neues Tierobjekt, namens loewe an.
loewe.tierGroesse=200;//Aufruf und Zuweisung durch Punktnotation
System.out.println("Das Tier ist "+loewe.tierGroesse+" Zentimeter groß.");
}
}



Stell dir einmal vor.
Du baust so ein Tier.
Und aus irgendeinem Grund weist du dem Tier keine Größe zu.

Dann hast du ein Tier ohne eine spezifische Größe.

Ist doch blöd oder?

Du solltest also die Möglichkeiten für dich und den Nutzer einschränken.

Man kann sagen:
Es sollte kein Tier angelegt werden, ohne dass ihm eine Größe zugewiesen wird.

Oder anders gesagt.
Du solltest bei der Erschaffung des Tieres schon die Größe festlegen müssen.

Und wie macht man das?
Indem man einen Java Konstruktor einsetzt.

Na das haben wir doch gerade, oder?
Ja aber dieser Konstruktor, nennt sich default-Konstruktor.
Das Wort default weist schon daraufhin, dass hier lediglich ein Standard angesprochen wurde.

Lass uns einen besseren Java Konstruktor für die Tierklasse anlegen.

Und so geht’s.

In deiner Tier Klasse, schreibst du jetzt einen richtigen Konstruktor.
Hier nochmal die Anweisung zum Aufruf des Default Konstruktors.
Tier loewe = new Tier ();

Da wir innerhalb der Klasse kein Objekt erschaffen wollen, fällt das Keyword new weg.
Alles andere wird so übernommen.

Die Beispielklasse Tier:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert


Tier (){ //Ein parameterloser Konstruktor
}
}

Du hast jetzt einen parameterlosen Konstruktor angelegt.
Und der kann genau das Gleiche, wie der default-Konstruktor.

Da so ein Konstruktor auch immer etwas machen soll, dürfen die geschweiften Klammern nicht fehlen.

Genauso wie bei den Methoden, findet innerhalb der Klammern die Programmlogik statt.

Also schreibst du alles, was beim Erschaffen eines Java Objektes stattfinden soll, in die Klammern.

Und jetzt passt du den Konstruktor nach deinen Vorstellungen an.

Wie schon beschrieben, haben wir lediglich den default Konstruktor übernommen.

Wir wollen aber eine Nutzereingabe erzwingen.
Beim Erschaffen eines Tieres soll der Nutzer später unbedingt die Größe angeben müssen.

Das heißt, dem Konstruktor fehlt ein Parameter.
Wir müssen dem Konstruktor die Instanzvariable „groesse“ mitgeben.

Und genau das versuchen wir jetzt.
Lass uns das ganze mal beim Programmstart testen.

Die Beispielklasse Tier mit Parameter im Konstruktor:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert


Tier (int tierGroesse){ //Der Konstruktor erwartet jetzt eine Zahl
}
}


Zum Programmstart bekommt der Konstruktor eine Größe von 300 Zentimetern zugewiesen:

public class ProgrammStart{
public static void main (String [] args) {
Tier loewe = new Tier (300);//Löwe soll 300 cm groß sein.
System.out.println("Das Tier ist "+loewe.tierGroesse+" Zentimeter groß.");
}
}

Starte das Programm.

Was ist passiert?
Anscheinend wurde der Wert unserer Instanzvariable nicht überschrieben.

Der Löwe ist nur 156 Zentimeter groß, anstatt 300.

Tja….
Was soll das? Ich will doch lediglich ein neues Tier erschaffen und diesem Tier von Anfang an eine Größe zuweisen.
Kann doch nicht so schwer sein, oder?

Ist es auch nicht.
Doch wir haben eines nicht beachtet.
Genau wie in Methoden, sind die Parameter, welche wir dem Konstruktor mitgeben immer lokale Variablen.

Das heißt diese Variable existiert außerhalb des Konstruktors nicht.

Und was ist mit der Variable ganz oben im Code?
Wir haben die Größe doch als Instanzvariable deklariert.

Und genau das ist das Problem.

Wir haben eine Instanzvariable groesse vom Datentyp Integer.
Und jetzt sagen wir:
„Liebes Programm leg mir eine zweite lokale Variable vom Datentyp Integer am Speicherort groesse an.“

Jetzt sagt unser Programm:
„Klar mach ich. Aber diese ist lokal. Außerhalb des Konstruktorrumpfes gibt es diese Variable nicht.“

Das heißt für Dich:
Du musst sie im Rumpf verarbeiten.

Okay, machen wir.
Du lässt also die lokale Variable stehen.
Es ist scheißegal, ob diese danach noch existiert.

Und du überschreibst den Wert der Instanzvariablen mit dem Wert der lokalen.

Und so könnte es aussehen.
Probier es ruhig einmal aus und sieh selbst, was passiert.

Die Beispielklasse Tier mit Parameter im Konstruktor:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert


Tier (int tierGroesse){ //Der Konstruktor erwartet jetzt eine Zahl
tierGroesse=tierGroesse;//Zuweisung der lokalen Variablen
}
}

Starte das Programm nochmal und schau was passiert. (Die Klasse ProgrammStart starten)

Zu blöd immer noch der falsche Wert.

Ja anscheinend haben wir jetzt lediglich die lokale Variable überschrieben.

Ich machs jetzt kurz.
Die lokale Variable muss einen anderen Namen haben, als die Instanzvariable.

Tierklasse mit richtiger lokaler Variablen:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert


//der Parameter bekommt jetzt einen anderen Namen. Aus tierGroesse wird dieTierGroesse
Tier (int dieTierGroesse){
tierGroesse=dieTierGroesse;//Überschreibt die Instanzvariable tierGroesse mit dem Wert der lokalen Variablen
}
}

Anmerkung:
Der Name der lokalen Variablen in der Parameterliste ist völlig egal.
Es bietet sich aber an, den Namen so zu wählen, dass der Zusammenhang zur Instanzvariablen erkennbar ist.

Was allerdings sehr wichtig ist.
Die lokale Variable muss den gleichen Datentyp haben, wie die Instanzvariable.

Starte doch einfach mal das Programm und erschaffe ein neues Tier.

Zum Programmstart bekommt der Konstruktor eine Größe von 300 Zentimetern zugewiesen:

public class ProgrammStart{
public static void main (String [] args) {
Tier loewe = new Tier (300);//Löwe soll 300 cm groß sein.
System.out.println("Das Tier ist "+loewe.tierGroesse+" Zentimeter groß.");
}
}

In der Konsole wird jetzt die richtige Zahl ausgegeben.

Cool es klappt.
Jetzt lass uns den Konstruktor erweitern.

Jedes Tierobjekt muss natürlich einer Art angehören.

Also setze in die Parameterliste wieder eine lokale Variable vom Typ String ein.
Und dann überschreibst du im Konstruktorrumpf den Wert der Instanzvariablen tierArt.
Trenne die Parameter durch ein Komma.

Tierklasse mit zwei Parametern:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert


Tier (int dieTierGroesse, String dieTierArt ){ //zwei Parameter
tierGroesse=dieTierGroesse;//Zuweisung der Größe
tierArt=dieTierArt;//Zuweisung der Art
}
}

Beim Programmstart müssen wir dem Konstruktor jetzt zwei Parameter mitgeben und wir können die System.out.println() Anweisung flexibler machen.

Zum Programmstart bekommt der Java Konstruktor 2 Parameter zugewiesen:

public class ProgrammStart{
public static void main (String [] args) {
Tier loewe = new Tier (300, "Der Löwe");//2 Parameter übergeben
System.out.println(loewe.tierArt+" ist "+loewe.tierGroesse+" Zentimeter groß.");//Anstatt das Tier können wir einen flexiblen Namen einsetzen
}
}

Lass das Programm einmal laufen.

Was mich jetzt noch stört, ist die Bildschirmausgabe.
Diese soll doch gleich beim Erschaffen eines neuen Tieres erfolgen.

Lass uns die Bildschirmausgabe deshalb aus der main-Methode entfernen und diese in den Konstruktorrumpf stecken.
Dann haben wir bei jedem neuen Tier sofort und immer eine Rückgabe auf der Konsole.

Ist doch besser, oder?

Und so sieht der Code danach aus.

Tierklasse und Bildschirmausgabe im Konstruktor:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert


Tier (int dieTierGroesse, String dieTierArt ){ //zwei Parameter
tierGroesse=dieTierGroesse;//Zuweisung der Größe
tierArt=dieTierArt;//Zuweisung der Art
//Da das Objekt (loewe) erst zum Programmstart existiert, darfst du nur die Instanzvariablen einsetzen. Das Objekt "loewe" existiert ja noch nicht. Somit wird aus loewe.tierArt nur noch tierArt.... usw.
System.out.println(tierArt+" ist "+tierGroesse+" Zentimeter groß.");
}
}


Die Klasse Programmstart erschafft das Tier. Die Bildschirmausgabe macht jetzt der Konstruktor.

public class ProgrammStart{
public static void main (String [] args) {
Tier loewe = new Tier (300, "Der Löwe");//2 Parameter übergeben
}
}

Starte jetzt das Programm und die Bildschirmausgabe wird direkt aus dem Konstruktor heraus erzeugt.

Wenn wir jetzt unser Programm so anschauen, haben wir an Eines nicht gedacht,

Und zwar muss jedes Tier eine bestimmte Größe haben.
Was ist aber, wenn wir gerade kein Werkzeug zum Messen dabei haben.

Oder jedes Tier muss zwingend einer bestimmten Art angehören.
Was ist aber, wenn wir die Art nicht wissen.

Oder noch viel cooler wäre es – Wir entdecken eine neue Art.

Wir müssen also den Konstruktor noch etwas flexibler machen.

Nein nicht flexibler.
Wir brauchen mehrere Java Konstruktoren. Und so könnten diese aussehen.

  1. Konstruktor 1: Nimmt zwingend die Größe und Art entgegen. Der Konstruktor soll dann eine Bildschirmausgabe erzeugen: „Wir haben ein neues Tier aufgenommen. Art: (und jetzt folgt die Tierart) Größe: ( und jetzt folgt die Größe)
  2. Konstruktor 2: Nimmt nur die Größe entgegen. Die Bildschirmausgabe soll lauten: „Hurra wir haben eine neue Tierart entdeckt. Die Größe beträgt: (jetzt folgt die Größe)
  3. Konstruktor 3: Nimmt nur die Tierart entgegen. Die Bildschirmausgabe soll lauten: „Wir haben ein neues Tier aufgenommen. Art: (jetzt folgt die Tierart).“ „Eh Mann wo ist mein Maßband“

Wenn du mehrere Konstruktoren schaffst, welche ein und dieselben Java Objekte erschaffen –
Dann nennt man so etwas überladen.

Lass uns mal die Java Konstruktoren überladen

Es ist ganz einfach.

Du legst einfach mehrere Konstruktoren in der Java Klasse an.
Und diesen gibst du dann unterschiedliche Parameterlisten mit.

Dadurch wird die Erschaffung eines Tier-Objektes recht flexibel.

Und so sieht der Code dazu aus.

Tierklasse mit drei Java Konstruktoren:

public class Tier{
int tierGroesse=156;//Größe in Zentimeter
String tierArt;//Art des Tieres als Textwert


//Konstruktor 1 nimmt Größe und Art entgegen
Tier (int dieTierGroesse, String dieTierArt ){ //zwei Parameter
tierGroesse=dieTierGroesse;//Zuweisung der Größe
tierArt=dieTierArt;//Zuweisung der Art
System.out.println("Wir haben ein neues Tier aufgenommen. Art: "+tierArt+" Größe: "+tierGroesse);
}


//Konstruktor 2 nimmt nur Größe entgegen
Tier (int dieTierGroesse){ //ein Parameter
tierGroesse=dieTierGroesse;//Zuweisung der Größe
System.out.println("Hurra wir haben eine neue Tierart entdeckt. Die Größe beträgt: "+tierGroesse);
}


//Konstruktor 3 nimmt nur die Art entgegen
Tier (String dieTierArt ){ //ein Parameter
tierArt=dieTierArt;//Zuweisung der Art
System.out.println("Wir haben ein neues Tier aufgenommen. Art: "+tierArt+ " Eh Mann, wo ist mein Maßband?");
}
}

In der main Methode schaffst du drei unterschiedliche Tierobjekte und führst das Programm dann aus.

Die Klasse Programmstart erschafft drei Tiere. Die Bildschirmausgabe macht jetzt der Konstruktor.

public class ProgrammStart{
public static void main (String [] args) {


Tier loewe = new Tier (300, "Löwe");//2 Parameter übergeben
Tier tiger = new Tier ("Tiger");//nur die Tierart ist bekannt
Tier unbekannt = new Tier (200);//nur die Größe ist bekannt
}
}

Zusammenfassung:

  • Um ein Java Objekt zu schaffen, benötigst du immer einen Konstruktor.
  • Dieser Konstruktor wird immer durch das Keyword new aufgerufen.
  • Einem Konstruktor kannst du verschiedene Parameter mitgeben.
    Die Parameter zwingen den Nutzer dazu, dass er bei der Erstellung eines Objektes sofort Eigenschaften festlegen muss.
  • Um das ganze dennoch flexibel zu gestalten, solltest du mehrere Java Konstruktoren mit unterschiedlichen Parameterlisten anlegen.
  • Das Konzept mehrere Konstruktoren in einer Java Klasse zu führen, nennt sich überladen.

Ähnliche Beiträge

Java Übung 21 – Bestimme die Anzahl der Tage

Java Übung Tage

In dieser Java Übung möchte ich, dass du eine Methode schreibst, welche zwei Zahlen entgegennimmt. Und zwar soll die erste Zahl das Jahr sein. Die zweite Zahl soll eine Monatsangabe (1-12) repräsentieren. Was soll die Methode dann machen? Die Methode soll dir die Anzahl der Tage des jeweiligen Monats zurückgeben. Achte auf Schaltjahre.

Java Vererbung:
Die 3 Schablonen für deine Java Objekte

Java Vererbung Beispiel

Im letzten Beitrag habe ich dir das Java Vererbung Konzept an einem Beispiel vorgestellt. In dem Beispiel-Rollenspiel gab es Klassen zu Helden und Superhelden. Ich habe dir die Vererbungshierarchien theoretisch erläutert. Jetzt geht es ans Praktische. In diesen Beitrag lernst du: Wie du bestehende Java Klassen erweiterst Wie du Objekte aus den erweiterten Klassen erstellen […]

So verwendest du den Java Oder Operator

Java Oder Operator

Kennst du das auch aus deiner Schulzeit? Du schreibst eine Klassenarbeit in irgendeinem Fach. Nehmen wir einfach mal an – Mathe. Jetzt bist gerade fertig mit deiner Arbeit. Und zu Hause wirst du gefragt: „Und wie lief es?“ Du antwortet:“ Ganz gut. Es wird bestimmt eine Eins oder eine Zwei.“ Drei oder vier Tage später […]

8 Java Datentypen, die du kennen solltest

Java Datentypen

Java Datentypen Ich gebe zu, ich hasse dieses Thema. Denn es ist eigentlich nichts weiter als graue Theorie. Dennoch müssen wir dieses Thema behandeln. Um schnell in das Thema zu kommen, stelle ich dir eine Übersicht aller primitiven Datentypen zur Verfügung. Wieso primitive? Es gibt außer den primitiven Datentypen, noch Referenztypen. Und diese Referenztypen sind […]

Java Strings landen im String Constant Pool

Java-Strings-Pool

Du kennst das. Es ist abends. Du sitzt gemütlich vor dem Fernseher. Das Smartphone bimmelt. Kein Anruf. Nein – Eine Nachricht. Du liest die Nachricht sofort und antwortest darauf. Minuten später bekommst du die nächste Nachricht. Und auch auf diese antwortest du. Im Laufe des Abends entsteht daraus eine nette kleine Konversation. Und eh du […]

Beim Aufruf werden Java Methoden auf dem Stack gestapelt

Java Methoden gestapelt

Java Methoden werden beim Aufruf gestapelt. Und jedes Element auf dem Stapel nimmt Speicherplatz weg. Und manchmal ist es so, dass der Stapel richtig hoch wird und dann…. Ja was passiert eigentlich dann? Betrachten wir einmal ein Computerspiel. Irgendeines. In diesem Computerspiel gibt es Vögel, welche abgeschossen werden sollen. Was bedeutet das denn genau? Beim […]

So kannst du Java Arrays mit for Schleife füllen und auslesen

Java Arrays For Schleife

Wir haben in einem anderen Beitrag bereits über Java Arrays gesprochen. So ein Array speichert Zahlen, Texte oder Objekte in eine Art Liste. Und dann kannst du ganz bequem über den Index das Array füllen und die bereits enthaltenen Werte abrufen. Ganz bequem? So, wie ich dich aus dem letzten Beitrag entlassen habe, war das […]

So verwendest du die Java Codeblöcke zur Automatisierung

Java Codeblöcke

In diesem Beitrag geht es um den Einsatz von Java Codeblöcken oder Initialisierungsblöcken. Viele Wege führen nach Rom. Oder Alle Wege führen nach Rom. Heißt es in einem alten Sprichwort. Und so ähnlich ist es bei der Java Programmierung. In diesem Beitrag möchte ich dir einen weiteren Weg vorstellen, wie du Variablen eines Java Objektes […]

Hier sind ein paar richtig nette Features, die dich beim Java lernen unterstützen

Java lernen Eclipse

Was ist das Wichtigste beim Einstieg in ein neues Wissensgebiet? Nein, kein gutes Sachbuch oder ein besonders guter Lehrer. Es ist Spaß. Beim Java Lernen brauchst du Spaß. Es gibt Lehrer, welche ihren Stoff so vermitteln, dass Lernen Spaß bereitet. Aber die Grundvoraussetzung ist und bleibt der Spaß. Und nichts ist so spaßhemmend wie Langeweile […]

Das Java Leben ist einfacher mit For-Schleife

Java For Schleife Aufbau

In einem anderen Artikeln habe ich bereits über Schleifen in Java gesprochen. In diesem Artikel möchte ich dir eine ganz besondere Schleife vorstellen. Warum ist diese so toll? Sie hat einen integrierten Schleifenzähler. Die Schleife zählt also bei jedem Durchlauf automatisch mit. Aber dazu gleich mehr…. Lass uns einmal so eine For Schleife anlegen.