Konstruktoren
Alles über Konstruktoren in Java: Default-Konstruktor, parametrisierte Konstruktoren, Konstruktor-Überladung und this()-Aufrufe.
Konstruktoren in Java
Im letzten Kapitel hast du Objekte mit new erstellt und dann die Felder einzeln gesetzt. Das ist umstaendlich und fehleranfaellig! Konstruktoren loesen dieses Problem: Sie initialisieren ein Objekt direkt bei der Erstellung.
Was ist ein Konstruktor?
Ein Konstruktor ist eine spezielle Methode, die beim Erstellen eines Objekts aufgerufen wird:
public class Hund {
String name;
String rasse;
int alter;
// Konstruktor
Hund(String name, String rasse, int alter) {
this.name = name;
this.rasse = rasse;
this.alter = alter;
}
}
// Objekt erstellen -- Konstruktor wird aufgerufen
var rex = new Hund("Rex", "Schaeferhund", 5);
Regeln fuer Konstruktoren
| Regel | Erlaeuterung |
|---|---|
| Name = Klassenname | Hund() fuer Klasse Hund |
| Kein Rueckgabetyp | Nicht mal void! |
Wird mit new aufgerufen | new Hund("Rex", "Schaeferhund", 5) |
| Kann ueberladen werden | Mehrere Konstruktoren mit verschiedenen Parametern |
Ohne Konstruktor: Der Default-Konstruktor
Wenn du keinen Konstruktor schreibst, erzeugt Java automatisch einen leeren Default-Konstruktor:
public class Katze {
String name;
int alter;
// Java erstellt automatisch: Katze() { }
}
var katze = new Katze(); // Default-Konstruktor
katze.name = "Mia"; // Felder einzeln setzen -- umstaendlich!
katze.alter = 3;
Achtung: Sobald du einen eigenen Konstruktor schreibst, gibt es den Default-Konstruktor nicht mehr:
public class Vogel {
String name;
Vogel(String name) {
this.name = name;
}
}
// var v = new Vogel(); // FEHLER! Kein Default-Konstruktor mehr!
var v = new Vogel("Tweety"); // OK
Konstruktor-Ueberladung
Du kannst mehrere Konstruktoren mit unterschiedlichen Parametern haben:
public class Auto {
String marke;
String modell;
int baujahr;
String farbe;
// Konstruktor mit allen Feldern
Auto(String marke, String modell, int baujahr, String farbe) {
this.marke = marke;
this.modell = modell;
this.baujahr = baujahr;
this.farbe = farbe;
}
// Konstruktor ohne Farbe (Standardfarbe)
Auto(String marke, String modell, int baujahr) {
this(marke, modell, baujahr, "Schwarz"); // Ruft anderen Konstruktor auf
}
// Konstruktor nur mit Marke und Modell
Auto(String marke, String modell) {
this(marke, modell, 2026); // Ruft den Konstruktor mit 3 Parametern auf
}
void info() {
System.out.printf("%s %s (%d) in %s%n", marke, modell, baujahr, farbe);
}
}
var auto1 = new Auto("BMW", "3er", 2024, "Weiss");
var auto2 = new Auto("VW", "Golf", 2023); // Farbe = Schwarz
var auto3 = new Auto("Audi", "A4"); // Baujahr = 2026, Farbe = Schwarz
auto1.info(); // BMW 3er (2024) in Weiss
auto2.info(); // VW Golf (2023) in Schwarz
auto3.info(); // Audi A4 (2026) in Schwarz
this() — Konstruktoren verketten
Mit this() rufst du einen anderen Konstruktor derselben Klasse auf:
public class Rechteck {
double breite;
double hoehe;
// Haupt-Konstruktor
Rechteck(double breite, double hoehe) {
this.breite = breite;
this.hoehe = hoehe;
}
// Quadrat-Konstruktor
Rechteck(double seite) {
this(seite, seite); // Ruft den Haupt-Konstruktor auf
}
// Standard-Konstruktor
Rechteck() {
this(1.0, 1.0); // Einheitsquadrat
}
double flaeche() {
return breite * hoehe;
}
}
Regel: this() muss die erste Anweisung im Konstruktor sein!
// FEHLER:
Rechteck(double seite) {
System.out.println("Erstelle Quadrat"); // FEHLER! this() muss zuerst kommen
this(seite, seite);
}
// RICHTIG:
Rechteck(double seite) {
this(seite, seite);
System.out.println("Quadrat erstellt"); // OK nach this()
}
Validierung im Konstruktor
Der Konstruktor ist der perfekte Ort, um Eingaben zu pruefen:
public class Temperatur {
private double celsius;
Temperatur(double celsius) {
if (celsius < -273.15) {
throw new IllegalArgumentException(
"Temperatur kann nicht unter -273.15°C liegen!"
);
}
this.celsius = celsius;
}
double inFahrenheit() {
return celsius * 9.0 / 5.0 + 32;
}
double inKelvin() {
return celsius + 273.15;
}
@Override
public String toString() {
return String.format("%.1f°C", celsius);
}
}
var temp = new Temperatur(36.6);
System.out.println(temp); // 36.6°C
System.out.println(temp.inFahrenheit()); // 97.88
System.out.println(temp.inKelvin()); // 309.75
// var falsch = new Temperatur(-500); // IllegalArgumentException!
Compact Constructors in Records
Records haben einen speziellen kompakten Konstruktor fuer Validierung:
record Alter(int wert) {
// Kompakter Konstruktor -- ohne Parameterliste!
Alter {
if (wert < 0 || wert > 150) {
throw new IllegalArgumentException("Ungueltiges Alter: " + wert);
}
}
}
var alter = new Alter(25); // OK
System.out.println(alter.wert()); // 25
// var ungueltig = new Alter(-5); // IllegalArgumentException!
record Email(String adresse) {
Email {
if (adresse == null || !adresse.contains("@")) {
throw new IllegalArgumentException("Ungueltige E-Mail: " + adresse);
}
adresse = adresse.toLowerCase().strip(); // Normalisierung
}
}
var email = new Email(" MAX@Example.COM ");
System.out.println(email.adresse()); // max@example.com
Copy-Konstruktor
Ein Konstruktor, der ein bestehendes Objekt kopiert:
public class Punkt {
double x;
double y;
Punkt(double x, double y) {
this.x = x;
this.y = y;
}
// Copy-Konstruktor
Punkt(Punkt anderer) {
this(anderer.x, anderer.y);
}
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
}
var original = new Punkt(3, 4);
var kopie = new Punkt(original);
kopie.x = 10;
System.out.println(original); // (3.0, 4.0) -- unveraendert
System.out.println(kopie); // (10.0, 4.0) -- eigene Kopie
Vergleich mit Python
# Python: __init__
class Hund:
def __init__(self, name, rasse, alter=0):
self.name = name
self.rasse = rasse
self.alter = alter
rex = Hund("Rex", "Schaeferhund", 5)
bella = Hund("Bella", "Pudel") # alter = 0 (Standardwert)
// Java: Konstruktor-Ueberladung
public class Hund {
String name;
String rasse;
int alter;
Hund(String name, String rasse, int alter) {
this.name = name;
this.rasse = rasse;
this.alter = alter;
}
Hund(String name, String rasse) {
this(name, rasse, 0); // Standardwert fuer alter
}
}
Python nutzt Standardwerte in Parametern, Java nutzt Konstruktor-Ueberladung.
Praktisches Beispiel: Spieler-Klasse
public class Spieler {
private String name;
private int level;
private int erfahrung;
private int maxHP;
private int aktuelleHP;
// Neuer Spieler
Spieler(String name) {
this(name, 1, 0);
}
// Spieler laden (aus Speicherstand)
Spieler(String name, int level, int erfahrung) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Name darf nicht leer sein!");
}
if (level < 1) {
throw new IllegalArgumentException("Level muss mindestens 1 sein!");
}
this.name = name;
this.level = level;
this.erfahrung = erfahrung;
this.maxHP = 100 + (level - 1) * 20;
this.aktuelleHP = maxHP;
}
void schadenNehmen(int schaden) {
aktuelleHP = Math.max(0, aktuelleHP - schaden);
if (aktuelleHP == 0) {
System.out.println(name + " ist besiegt!");
}
}
void heilen(int menge) {
aktuelleHP = Math.min(maxHP, aktuelleHP + menge);
}
@Override
public String toString() {
return "%s (Level %d) - HP: %d/%d".formatted(name, level, aktuelleHP, maxHP);
}
}
var held = new Spieler("Arthas");
System.out.println(held); // Arthas (Level 1) - HP: 100/100
held.schadenNehmen(30);
System.out.println(held); // Arthas (Level 1) - HP: 70/100
held.heilen(15);
System.out.println(held); // Arthas (Level 1) - HP: 85/100
Uebungen
Uebung 1: Kreis-Klasse
Erstelle eine Klasse Kreis mit einem Konstruktor, der den Radius entgegennimmt. Validiere, dass der Radius positiv ist. Fuege Methoden fuer Flaeche und Umfang hinzu.
Uebung 2: Buch-Konstruktoren
Erstelle eine Klasse Buch mit drei ueberladenen Konstruktoren:
Buch(String titel)— Autor = “Unbekannt”, Seiten = 0Buch(String titel, String autor)— Seiten = 0Buch(String titel, String autor, int seiten)— Alle Felder
Uebung 3: Bankkonto
Erstelle eine Klasse Bankkonto mit Validierung im Konstruktor (Inhaber darf nicht leer sein, Startguthaben >= 0). Fuege Methoden fuer Einzahlung und Abhebung hinzu.
Uebung 4: Record mit Validierung
Erstelle einen Record Passwort(String wert) mit Validierung: mindestens 8 Zeichen, mindestens eine Ziffer.
Was kommt als Naechstes?
In der naechsten Lektion lernst du Vererbung — wie Klassen Eigenschaften und Verhalten an andere Klassen weitergeben koennen.
Zusammenfassung
- Konstruktoren initialisieren Objekte bei der Erstellung mit
new - Sie haben den gleichen Namen wie die Klasse und keinen Rueckgabetyp
- Ohne eigenen Konstruktor gibt es einen Default-Konstruktor (leer)
- Konstruktor-Ueberladung ermoeglicht mehrere Erstellungswege
this()ruft einen anderen Konstruktor derselben Klasse auf- Konstruktoren sind ideal fuer Validierung von Eingabewerten
- Records haben kompakte Konstruktoren fuer Validierung und Normalisierung
Pro-Tipp: In IntelliJ kannst du Konstruktoren automatisch generieren lassen: Alt + Insert (oder Cmd + N auf macOS) > “Constructor”. Waehle die gewuenschten Felder aus, und IntelliJ erstellt den Konstruktor fuer dich — inklusive this-Zuweisungen. Das spart Zeit und vermeidet Tippfehler!