CodeGym /Kurse /JAVA 25 SELF /Record mit Methoden

Record mit Methoden

JAVA 25 SELF
Level 22, Lektion 3
Verfügbar

1. Erweiterung einer Record-classe: zusätzliche Methoden

Kann man einem Record Methoden hinzufügen?

Natürlich! Ein Record ist wie eine bezugsfertige Wohnung: Wände und Boden sind fertig, ändern kann man sie nicht, aber die Möbel darf man nach eigenem Geschmack stellen. Innerhalb eines record kann man normale Methoden, statische Methoden deklarieren und sogar Konstanten speichern. Das bedeutet, dass die Geschäftslogik nicht zwingend in separate „Utility“-classen ausgelagert werden muss – man kann sie sauber direkt in den record einbetten.

Beispiel: Methode zur Berechnung der Entfernung zwischen Punkten

Angenommen, wir haben einen record für einen Punkt in der Ebene:


public record Point(int x, int y) {
    // Zusätzliche Methode
    public double distanceTo(Point other) {
        int dx = this.x - other.x;
        int dy = this.y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Jetzt kann man Folgendes tun:


Point p1 = new Point(0, 0);
Point p2 = new Point(3, 4);
System.out.println(p1.distanceTo(p2)); // 5.0

Wie man sieht, lässt sich ein record mit eigenen Methoden „anreichern“ – und das ist sehr praktisch!

Beispiel: statische Methode


public record Rectangle(int width, int height) {
    public int area() {
        return width * height;
    }

    public static Rectangle square(int size) {
        return new Rectangle(size, size);
    }
}

Jetzt kann man ein „Quadrat“ mit einem einzigen Aufruf erzeugen:


Rectangle r = Rectangle.square(5);
System.out.println(r.area()); // 25

2. Kompakter Konstruktor und Datenvalidierung

Wozu braucht man einen „kompakten“ Konstruktor?

Der kanonische record-Konstruktor wird automatisch erzeugt und weist die Parameter den Komponenten zu. Manchmal möchte man jedoch Eingabedaten prüfen (zum Beispiel negative Koordinaten verbieten).

In einer normalen classe würden wir schreiben:


public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        if (x < 0 || y < 0) throw new IllegalArgumentException();
        this.x = x;
        this.y = y;
    }
    // ...
}

In einer record-classe kann man einen kompakten Konstruktor deklarieren – ohne die Parameterliste zu wiederholen und ohne die Komponenten explizit zuzuweisen (das übernimmt der Compiler).

Syntax des kompakten Konstruktors


public record Point(int x, int y) {
    public Point {
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("Coordinates must be non-negative");
        }
        // Das muss man nicht schreiben: this.x = x; this.y = y;
    }
}
  • Die Konstruktorparameter entsprechen automatisch den Komponenten des record.
  • Die Zuweisungen this.x = x und this.y = y führt der Compiler automatisch nach der Ausführung des Konstruktorkörpers (oder nach erfolgreichem Verlassen) aus.
  • Wenn eine Ausnahme ausgelöst wird, wird das Objekt nicht erstellt.

Beispiel mit Prüfung


Point p1 = new Point(3, 5); // OK
Point p2 = new Point(-1, 2); // wirft IllegalArgumentException!

Kann man einen „gewöhnlichen“ Konstruktor deklarieren?

Ja, kann man! Wenn Sie einen Konstruktor mit anderer Parameterliste oder zusätzlicher Logik benötigen, deklarieren Sie ihn explizit:


public record Range(int from, int to) {
    public Range(int size) {
        this(0, size); // ruft den Hauptkonstruktor auf
    }
}

3. Einschränkungen von Record-classen

Im Unterschied zu normalen classen haben record-classen eine Reihe von Einschränkungen. Das sollte man im Hinterkopf behalten, um sich nicht über Compilerfehler zu wundern.

Nur Komponenten – keine zusätzlichen nichtstatischen Felder

In einer record-classe darf man keine neuen nichtstatischen Felder deklarieren:


public record Person(String name, int age) {
    // int id; // Compilerfehler! Nichtstatische Felder dürfen nicht hinzugefügt werden.
}

Statische Felder und Methoden sind erlaubt:


public record Person(String name, int age) {
    public static final String SPECIES = "Homo sapiens";
}

Record ist immer final

Eine Record-classe kann keine Basisklasse sein (von ihr kann nicht geerbt werden) und sie kann selbst keine andere classe explizit erweitern (außer der impliziten Vererbung von java.lang.Record). Das bedeutet, dass eine record-classe immer eine „abschließende“ Struktur ist.


public record User(String login) { }

// public class Admin extends User {} // Fehler: von einem Record kann nicht geerbt werden!

Interfaces können implementiert werden

Record-classen können Interfaces implementieren:


public interface Printable {
    void print();
}

public record Invoice(int amount) implements Printable {
    @Override
    public void print() {
        System.out.println("Betrag: " + amount);
    }
}

4. Beispiele: erweiterte Records in realen Aufgaben

Schauen wir uns einige praktische Beispiele an, in denen zusätzliche Methoden und kompakte Konstruktoren eine record-classe wirklich nützlich machen.

Record mit berechneter Methode


public record Circle(double x, double y, double radius) {
    public double area() {
        return Math.PI * radius * radius;
    }

    public double distanceTo(Circle other) {
        double dx = x - other.x;
        double dy = y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Record mit Validierung


public record Email(String value) {
    public Email {
        if (value == null || !value.contains("@")) {
            throw new IllegalArgumentException("Ungültige E-Mail: " + value);
        }
    }
}

Nun lässt sich keine ungültige E-Mail erzeugen:


Email e1 = new Email("test@example.com"); // OK
Email e2 = new Email("not-an-email"); // wirft IllegalArgumentException

Record mit zusätzlichen statischen Methoden


public record Temperature(double celsius) {
    public static Temperature fromFahrenheit(double fahrenheit) {
        return new Temperature((fahrenheit - 32) * 5 / 9);
    }

    public double toFahrenheit() {
        return celsius * 9 / 5 + 32;
    }
}

Verwendung:


Temperature t = Temperature.fromFahrenheit(98.6);
System.out.println(t.celsius()); // 37.0
System.out.println(t.toFahrenheit()); // 98.6

5. Kompakter Konstruktor: Feinheiten und Einschränkungen

Wann sollte man den kompakten Konstruktor verwenden?

  • Wenn die Daten auf Korrektheit geprüft werden sollen (Validierung).
  • Wenn Werte vor dem Speichern angepasst werden sollen (z. B. eine Zahl runden oder eine Zeichenfolge in Großbuchstaben umwandeln).
  • Wenn die Duplizierung der Parameterliste vermieden werden soll.

Besonderheiten

  • Im kompakten Konstruktor darf man Komponenten nicht explizit zuweisen (this.x = ...) – das führt zu einem Compilerfehler, da der Compiler die Zuweisungen nach der Ausführung des Konstruktorkörpers selbst vornimmt.
  • Im kompakten Konstruktor dürfen die Parameternamen nicht geändert werden – sie stimmen stets mit den Komponentennamen des record überein.

Beispiel: automatische Rundung


public record Money(double amount) {
    public Money {
        amount = Math.round(amount * 100) / 100.0; // Auf zwei Nachkommastellen runden
    }
}

6. Praxis: wir erweitern eine Lernanwendung

Angenommen, wir entwickeln Bankoperationen in einer Lernanwendung. Nehmen wir einen record-class Transaction, der Betrag, Absender und Empfänger speichert.


public record Transaction(String from, String to, double amount) {
    public Transaction {
        if (amount <= 0) throw new IllegalArgumentException("Der Betrag muss positiv sein");
        if (from == null || to == null) throw new IllegalArgumentException("Felder dürfen nicht null sein");
    }

    public String description() {
        return String.format("Überweisung %.2f von %s an %s", amount, from, to);
    }
}

Verwendung:


Transaction t = new Transaction("Alice", "Bob", 150.0);
System.out.println(t.description()); // Überweisung 150.00 von Alice an Bob

Ein Versuch, eine ungültige Transaktion zu erstellen, führt zu einem Fehler:


Transaction t2 = new Transaction("Alice", "Bob", -10.0); // IllegalArgumentException

Tabelle: Was in einer Record-classe erlaubt ist und was nicht

Erlaubt in einer Record-classe Nicht erlaubt in einer Record-classe
Normale Methoden Neue nichtstatische Felder
Statische Methoden und Felder Von anderen classen erben
Interfaces implementieren Superklasse für andere sein
Kompakte und gewöhnliche Konstruktoren Komponenten nach der Erstellung verändern
Methoden überschreiben Setter verwenden

7. Typische Fehler beim Arbeiten mit Record-classen mit erweitertem Körper

Fehler Nr. 1: der Versuch, ein nichtstatisches Feld hinzuzufügen.
Anfänger versuchen häufig, einer record-classe „noch ein Feld für interne Logik“ hinzuzufügen – etwa einen Zähler oder Cache. Das funktioniert nicht: Der Compiler meldet sofort einen Fehler. Wenn Sie zusätzlichen Zustand speichern müssen, ist eine record-classe wahrscheinlich nicht die richtige Wahl.

Fehler Nr. 2: Validierung im kompakten Konstruktor vergessen.
Wenn ein Objekt stets valide sein soll, führen Sie die Prüfung im kompakten Konstruktor durch. Verlassen Sie sich nicht darauf, dass „der Benutzer schon nichts Unsinniges eingibt“.

Fehler Nr. 3: der Versuch, eine Komponente nach der Erstellung zu ändern.
Die Felder einer record-classe sind final – sie lassen sich weder direkt noch über Methoden ändern. Wenn Sie eine veränderliche Struktur brauchen, verwenden Sie eine normale classe.

Fehler Nr. 4: Duplizierung von Logik in Methoden und Konstruktor.
Mitunter versucht man, Prüf- und Berechnungslogik sowohl in Methoden als auch im Konstruktor zu duplizieren. Besser ist es, die gesamte Validierung im Konstruktor zu platzieren und die Methoden für „saubere“ Geschäftslogik zu belassen.

Fehler Nr. 5: Beschränkungen der Vererbung vergessen.
Record-classen sind immer final – man kann davon keinen Untertyp ableiten. Wenn Sie eine Hierarchie mit Unterklassen entwerfen, verwenden Sie normale classen.

1
Aufgabe
JAVA 25 SELF, Level 22, Lektion 3
Gesperrt
Temperaturmesswerte der Wetterstation 🌡️
Temperaturmesswerte der Wetterstation 🌡️
1
Aufgabe
JAVA 25 SELF, Level 22, Lektion 3
Gesperrt
Validierung der E-Mail-Adresse bei der Registrierung 📧
Validierung der E-Mail-Adresse bei der Registrierung 📧
1
Aufgabe
JAVA 25 SELF, Level 22, Lektion 3
Gesperrt
Erstellen einer Figurenkarte mit allgemeinen Angaben 🧍
Erstellen einer Figurenkarte mit allgemeinen Angaben 🧍
1
Aufgabe
JAVA 25 SELF, Level 22, Lektion 3
Gesperrt
Registrierung finanzieller Transaktionen bei der Bank 💸
Registrierung finanzieller Transaktionen bei der Bank 💸
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION