Menu
CoddyTech

Gebundene Typparameter

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 56 von 87.

Bisher können unsere generischen Typparameter jeden Typ akzeptieren. Aber was ist, wenn du sie einschränken musst?

Zum Beispiel sollte eine Methode, die die Summe von Zahlen berechnet, keine Zeichenketten akzeptieren. Mit begrenzten Typparametern kannst du einschränken, welche Typen mit deinen Generics verwendet werden können.

Verwende das Schlüsselwort extends, um eine obere Grenze für einen Typparameter festzulegen:

class NumberBox<T extends Number> {
    private T value;
    
    public NumberBox(T value) {
        this.value = value;
    }
    
    public double getDoubleValue() {
        return value.doubleValue();  // Kann Number-Methoden aufrufen!
    }
}

NumberBox<Integer> intBox = new NumberBox<>(42);
NumberBox<Double> doubleBox = new NumberBox<>(3.14);
// NumberBox<String> strBox = new NumberBox<>("Hi");  // Kompilierfehler!

Die Begrenzung T extends Number bedeutet, dass T Number oder eine beliebige seiner Unterklassen (Integer, Double usw.) sein muss. Dadurch kannst du außerdem auf dem Typparameter die in Number definierten Methoden aufrufen.

Du kannst mehrere Grenzen mit & angeben. Wenn eine Grenze eine Klasse ist, muss sie zuerst kommen:

class DataProcessor<T extends Number & Comparable<T>> {
    public boolean isGreater(T a, T b) {
        return a.compareTo(b) > 0;
    }
}

Hier muss T Number erweitern UND Comparable implementieren. Beschränkte Typparameter funktionieren auch mit generischen Methoden:

public static <T extends Comparable<T>> T findMax(T a, T b) {
    return a.compareTo(b) > 0 ? a : b;
}

String result = findMax("apple", "banana");  // Gibt "banana" zurück

Begrenzte Typparameter machen deine Generics leistungsfähiger, indem sie Typsicherheit gewährleisten und gleichzeitig den Zugriff auf bestimmte Methoden des gebundenen Typs ermöglichen.

challenge icon

Aufgabe

Einfach

Lass uns einen Statistikrechner erstellen, der nur mit numerischen Typen funktioniert! Du wirst begrenzte Typparameter verwenden, um sicherzustellen, dass dein Rechner nur Zahlen verarbeiten kann, und erhältst dabei Zugriff auf nützliche Methoden der Klasse Number.

Du wirst deinen Code auf drei Dateien verteilen:

  • NumberStats.java: Erstelle eine generische Klasse, die Statistiken für numerische Werte berechnet. Deine Klasse NumberStats<T extends Number> sollte zwei private Felder vom Typ T speichern: value1 und value2. Füge einen Konstruktor hinzu, der beide Werte akzeptiert. Füge eine Methode getSum() hinzu, die die Summe beider Werte als double zurückgibt (verwende die von Number geerbte Methode doubleValue()). Füge außerdem eine Methode getAverage() hinzu, die den Durchschnitt der beiden Werte als double zurückgibt.
  • ComparableBox.java: Erstelle eine generische Klasse mit mehreren Schranken, die den größeren von zwei Werten finden kann. Deine Klasse ComparableBox<T extends Number & Comparable<T>> sollte zwei private Felder vom Typ T speichern: first und second. Füge einen Konstruktor hinzu, der beide Werte akzeptiert. Füge eine Methode getMax() hinzu, die mithilfe von compareTo() den größeren Wert zurückgibt. Füge außerdem eine Methode getMaxAsDouble() hinzu, die den größeren Wert in einen double umwandelt.
  • Main.java: Erwecke deine begrenzten Generics zum Leben! Du erhältst vier Eingaben: zwei Ganzzahlen und zwei Gleitkommazahlen.

    Erstelle zuerst ein NumberStats<Integer> mit den beiden Ganzzahlwerten. Gib die Summe und den Durchschnitt aus:

    Integer sum: [sum]
    Integer average: [average]

    Erstelle als Nächstes ein NumberStats<Double> mit den beiden Gleitkommazahlen. Gib die Summe und den Durchschnitt aus:

    Double sum: [sum]
    Double average: [average]

    Erstelle schließlich ein ComparableBox<Integer> mit den beiden Ganzzahlwerten und gib Folgendes aus:

    Max integer: [max]
    Max as double: [maxAsDouble]

Du erhältst vier Eingaben in dieser Reihenfolge: erste Ganzzahl, zweite Ganzzahl, erste Gleitkommazahl, zweite Gleitkommazahl.

Beachte, wie die Schranke T extends Number es dir ermöglicht, doubleValue() für deinen generischen Typ aufzurufen. Das wäre mit einem unbegrenzten Typparameter nicht möglich. Und die mehreren Schranken in ComparableBox stellen sicher, dass du sowohl in einen double umwandeln als auch Werte vergleichen kannst!

Probier es selbst

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Eingaben lesen
        int int1 = scanner.nextInt();
        int int2 = scanner.nextInt();
        double double1 = scanner.nextDouble();
        double double2 = scanner.nextDouble();
        
        // TODO: Erstelle ein NumberStats<Integer> mit den beiden Integer-Werten
        // Gib die Summe und den Durchschnitt im folgenden Format aus:
        // Integer sum: [sum]
        // Integer average: [average]
        
        // TODO: Erstelle ein NumberStats<Double> mit den beiden Double-Werten
        // Gib die Summe und den Durchschnitt im folgenden Format aus:
        // Double sum: [sum]
        // Double average: [average]
        
        // TODO: Erstelle ein ComparableBox<Integer> mit den beiden Integer-Werten
        // Gib das Maximum und das Maximum als Double im folgenden Format aus:
        // Max integer: [max]
        // Max as double: [maxAsDouble]
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Java-Compiler