Übungsaufgaben zu generischen Klassen und Typparametern

https://bildung.social/@oerinformatik/

https://oer-informatik.de/generische-klassen-uebungsaufgaben

Generische Klassen, Typparameter, Typargument, Typsicherheit, Vergleicher, Comparator, Fehleranalyse, UML-Klassendiagramm, Template, Map, Übungsaufgaben, Prüfungsvorbereitung

tl/dr; (ca. 55 min Lese- und Bearbeitungszeit): Eine umfangreiche Übungsaufgabe rund um generische Klassen im Backend einer Freizeit-App: den Begriff erläutern, Listen mit Object und mit Typparameter vergleichen, eine generische Prüfmethode mit Vergleicher<T> analysieren und korrigieren, einen mehrstufigen Vergleich schreiben, eine generische Warteliste programmieren, fehlerhaften Code analysieren, Typparameter einschränken, Templates im UML-Klassendiagramm zeichnen und Map<K, V> verwenden. Alle Lösungen sind ausgeblendet und mit Punkteverteilung versehen [AI-Assisted]. (Zuletzt geändert am 28.10.2026)

Diese Übungsaufgaben gehören zum Artikel Generische Klassen und Typparameter. Sie setzen voraus, dass Du Sortieralgorithmen und Vergleichsfunktionen kennst und UML-Klassendiagramme lesen kannst.

Hinweise zur Bearbeitung: Von FIA wird erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1) keine Probleme bereiten. Wenn nichts anderes verlangt ist, darfst Du Deine Algorithmen in Pseudocode, als Struktogramm oder als Programmablaufplan angeben. Listen beginnen mit dem Index 0. Die Beispiellösungen verwenden die Java-nahe Schreibweise aus dem Artikel; andere korrekte Lösungen sind ebenfalls richtig. Schreib Deine Lösung zuerst vollständig auf, bevor Du die Beispiellösung aufklappst.

Du möchtest eigene Aufgaben zum Üben von einem KI-Sprachmodell generieren lassen?

Kopiere den Text in ein KI-Sprachmodell Deiner Wahl und passe Kompetenzstufe, Anzahl, Bearbeitungszeit und Szenario bei Bedarf an. Wie die Aufgaben aufgebaut sind, beschreibt der Artikel Wie sind die Aufgaben aufgebaut?. Prüfe die Ergebnisse mit dem Lehrartikel: KI-Sprachmodelle machen Fehler.

Erstelle neue Übungsaufgaben zum Thema „Generische Klassen und
Typparameter“.

Bauplan: Halte Dich an Aufbau, Kompetenzstufen, Operatoren,
Anforderungsbereiche, Punkte und Zeitschätzung, die im Artikel
https://oer-informatik.de/aufgaben-aufbau beschrieben sind.

Fachliche Grundlage:
- https://oer-informatik.de/generische-klassen
- https://oer-informatik.de/sortieralgorithmen
- https://oer-informatik.de/uml-klassendiagramm
- https://oer-informatik.de/algorithmen-objektorientiert
- Stilbeispiel: https://oer-informatik.de/generische-klassen-uebungsaufgaben

Die Aufgaben sollen Inhalte zu diesen Schlagwörtern abdecken:
- Generische Klassen
- Typparameter
- Typargument
- Typsicherheit
- Vergleicher
- Comparator
- Fehleranalyse
- UML-Klassendiagramm
- Template
- Map

Kompetenzstufe: Profilkompetenz (alternativ: Basiskompetenz, Kernkompetenz, Expertise)
Anzahl: 1 Aufgabe mit Teilaufgaben
Bearbeitungszeit in Minuten ca.: <5 bis 30 min>
Szenario: eines der Szenarien aus dem Bauplan

Vorgehen:
1. Lies zuerst die verlinkten Artikel. Kannst Du keine Webseiten
   abrufen, sag mir das, statt zu raten.
2. Steht bei einer Angabe noch ein Platzhalter in <…>, frag mich
   zuerst danach. Richte Punkte und Zahl der Teilaufgaben nach der
   Bearbeitungszeit (ca. 0,9 min je Punkt).
3. Gib je Aufgabe Titel mit Kompetenzstufe, Ausgangssituation und
   Teilaufgaben mit Operator und Punktzahl aus, dazu die geschätzte
   Bearbeitungszeit.
4. Gib die Beispiellösungen mit Punkteverteilung erst aus, wenn ich
   danach frage.

Aufgabe 3.1: Wiederverwendbare Listen im Backend einer Freizeit-App (Profilkompetenz)

Du bist Auszubildende*r bei der Let’s Meet GmbH in Bielefeld. Die App „Let’s Meet“ bringt Menschen für gemeinsame Freizeitaktivitäten zusammen – Wanderungen, Brettspielabende, Bouldern, Sprachtandems. Das Team baut das Backend neu auf. Yusuf Demir, Leiter der Entwicklung, hat bei einem Code-Review festgestellt, dass Dein Mit-Azubi Jonas Weber für Aktivitäten, Treffpunkte und Bewertungen jeweils eigene, fast gleiche Sortier- und Listenmethoden geschrieben hat. Yusuf möchte das mit generischen Klassen vereinheitlichen und bittet Dich um Unterstützung.

Für die Aufgabe steht die generische Klasse List<T> mit folgenden Methoden zur Verfügung:

Methoden der generischen Klasse List<T>
Methode Beschreibung
List() Konstruktor, erzeugt eine leere Liste
add(element: T): void hängt element am Ende an
get(index: Integer): T liefert das Element an der Position index
remove(index: Integer): void entfernt das Element an der Position index; alle folgenden Elemente rücken eine Position nach vorne
size(): Integer liefert die Anzahl der Elemente

Für Vergleiche hat Yusuf im Projekt eine eigene generische Schnittstelle angelegt, die Javas Comparator<T> nachempfunden ist:

interface Vergleicher<T> {
    + Integer vergleiche(T a, T b)    // < 0: a vor b,  0: gleichrangig,  > 0: a hinter b
}

Eine Klasse, die z. B. Vergleicher<Aktivitaet> implementiert, legt fest, in welcher Reihenfolge Aktivitäten stehen sollen. Ein Objekt dieser Klasse wird mit new erzeugt und an Methoden übergeben.

a) Jonas fragt Dich, was List<T> eigentlich von einer gewöhnlichen Klasse wie Aktivitaet unterscheidet. Erkläre es ihm: Wofür steht das T, was ändert sich, wenn jemand List<Aktivitaet> schreibt, und was hat das Team davon? Verwende dabei die Begriffe Typparameter und Typargument. (4 Punkte)

List<T> ist eine generische Klasse: Ihr Code legt sich nicht auf einen Elementtyp fest. Das T ist ein Typparameter, also ein Platzhalter, den die Klasse überall dort verwendet, wo sonst ein konkreter Typ stünde – etwa beim Parameter von add oder beim Rückgabewert von get (1 Punkt). Wer die Liste benutzt, setzt einen konkreten Typ ein, das Typargument: Bei List<Aktivitaet> ist das Aktivitaet, bei List<Treffpunkt> ist es Treffpunkt (1 Punkt). Für diese Variable verhalten sich die Methoden dann so, als wären sie für den eingesetzten Typ geschrieben: add akzeptiert nur Aktivitäten, get liefert eine Aktivitaet (1 Punkt). Die Listenlogik gibt es dadurch nur einmal, und trotzdem fallen falsche Typen schon beim Übersetzen auf statt erst im laufenden Programm (1 Punkt).

b) Im Altsystem des früheren Dienstleisters gab es eine Klasse ObjektListe, die Elemente vom Typ Object speichert. Alle Klassen erben von Object. Jonas zeigt Dir folgenden Ausschnitt aus der Verwaltung der Wartelisten:

ObjektListe wartende = new ObjektListe()
wartende.add(teilnahmeLea)                         // Objekt der Klasse Teilnahme
wartende.add(benutzerKim)                          // Objekt der Klasse Benutzer
Teilnahme t = (Teilnahme) wartende.get(1)          // Typumwandlung (Cast)

ba) Beschreibe, was beim Ausführen der letzten Zeile passiert, und begründe, warum der Compiler den Fehler beim Übersetzen nicht erkennen kann. (3 Punkte)

  • An Position 1 steht ein Benutzer-Objekt. Die Typumwandlung in Teilnahme schlägt zur Laufzeit fehl (in Java ClassCastException); das Programm bricht an dieser Stelle ab, wenn der Fehler nicht abgefangen wird (2 Punkte).

  • Der Compiler kennt nur den deklarierten Typ Object. add(Object) nimmt jedes Objekt an, und ob das Objekt an Position 1 wirklich eine Teilnahme ist, hängt vom Programmablauf ab – mit dem Cast wird nur „versprochen“, dass es passt (1 Punkt).

bb) Nenne zwei Vorteile, die eine generische Klasse wie List<Teilnahme> gegenüber der ObjektListe hat, und zwei Vorteile gegenüber eigenen Listenklassen für jeden Typ (TeilnahmeListe, BenutzerListe …). (4 Punkte)

Gegenüber ObjektListe (je 1 Punkt):

  • Typsicherheit zur Übersetzungszeit: add(benutzerKim) in eine List<Teilnahme> wird schon vom Compiler abgelehnt; der Fehler kann nicht erst im laufenden Betrieb auftreten.

  • Keine Typumwandlung nötig: get liefert direkt eine Teilnahme; der Code wird kürzer und lesbarer.

  • (alternativ) Die Entwicklungsumgebung kann Methoden des Elementtyps vorschlagen; die Absicht („Liste von Teilnahmen“) ist im Code dokumentiert.

Gegenüber eigenen Listenklassen je Typ (je 1 Punkt):

  • Wiederverwendung, keine Codeduplikation: Die Listenlogik existiert nur einmal; neue Typen brauchen keine neue Klasse.

  • Wartbarkeit: Ein Fehler in der Listenlogik wird an einer Stelle behoben und gilt für alle Typen; einheitliche Methoden für alle Listen.

c) Die App lädt manche Listen schon vorsortiert vom Server. Bevor sie erneut sortiert, soll eine generische Methode prüfen, ob eine Liste bereits in der gewünschten Reihenfolge vorliegt. Jonas hat einen ersten Entwurf geschrieben und ihn an Aktivitäten (Methode getKostenEur(): Double) ausprobiert:

Boolean istSortiert(List<T> liste, Vergleicher<T> v) {
    for (Integer i = 0; i < liste.size(); i++) {
        if (liste[i].getKostenEur() > liste[i + 1].getKostenEur()) {
            return false
        }
    }
    return true
}

ca) Yusuf meint beim Review: „Der Kopf ist generisch, der Rumpf nicht – und laufen würde es auch nicht.“ Nenne drei Fehler im Entwurf, begründe jeweils, warum es sich um einen Fehler handelt, und gib an, welcher davon erst beim Ausführen auffallen würde. (4 Punkte)

Je Fehler mit Begründung 1 Punkt:

  • Getter auf T: getKostenEur() gibt es nur bei Aktivitaet. Ein beliebiges T (z. B. Treffpunkt) hat diese Methode nicht, die Methode lässt sich so nicht übersetzen. Der übergebene Vergleicher v wird gar nicht benutzt, obwohl genau er den Vergleich liefern soll.

  • Array-Zugriff auf einer Liste: liste[i] ist für ein List<T>-Objekt nicht definiert; gelesen wird mit liste.get(i).

  • Schleifengrenze: Im letzten Durchlauf ist i = liste.size() - 1, der Zugriff auf i + 1 liegt dann hinter dem letzten Element (Indexfehler zur Laufzeit). Die Schleife darf nur bis i < liste.size() - 1 laufen.

Die ersten beiden Fehler meldet schon der Compiler; der Indexfehler fällt erst beim Ausführen auf, und zwar bei jeder Liste mit mindestens einem Element, deren Nachbarn bis zum Ende richtig geordnet sind (1 Punkt).

cb) Schreibe die Methode istSortiert so, dass sie für jede Liste mit passendem Vergleicher funktioniert. Gleichrangige Nachbarn gelten als richtig sortiert; eine leere Liste und eine Liste mit nur einem Element ebenfalls. (4 Punkte)

Boolean istSortiert(List<T> liste, Vergleicher<T> v) {
    for (Integer i = 0; i < liste.size() - 1; i++) {
        if (v.vergleiche(liste.get(i), liste.get(i + 1)) > 0) {
            return false
        }
    }
    return true
}

Bewertung:

  • Schleifengrenze liste.size() - 1, sodass immer zwei Nachbarn existieren (1 Punkt)

  • Zugriffe mit get (1 Punkt)

  • Vergleich nur über v.vergleiche(…) mit > 0; bei >= 0 würden gleichrangige Nachbarn fälschlich als unsortiert gelten (1 Punkt)

  • false beim ersten falsch geordneten Paar, true erst nach der Schleife (1 Punkt)

Leere Liste und Liste mit einem Element brauchen keinen Sonderfall: Die Bedingung 0 < -1 bzw. 0 < 0 ist sofort falsch, die Methode liefert true.

d) Auf der Karte der App sollen die Treffpunkte geordnet aufgelistet werden. Die Klasse Treffpunkt besitzt die Methoden getId(): Integer, getStadtteil(): String und getName(): String. Zwei Zeichenketten vergleichst Du mit s1.compareTo(s2): Das Ergebnis ist negativ, wenn s1 alphabetisch vor s2 steht, 0 bei gleichem Text und sonst positiv.

da) Erstelle eine Klasse NachStadtteilUndName, die Vergleicher<Treffpunkt> implementiert. Treffpunkte werden zuerst alphabetisch nach Stadtteil geordnet; nur bei gleichem Stadtteil entscheidet der Name. (4 Punkte)

class NachStadtteilUndName implements Vergleicher<Treffpunkt> {
    + Integer vergleiche(Treffpunkt a, Treffpunkt b) {
        Integer ergebnis = a.getStadtteil().compareTo(b.getStadtteil())
        if (ergebnis != 0) {
            return ergebnis
        }
        return a.getName().compareTo(b.getName())
    }
}

Bewertung: Klassenkopf mit implements Vergleicher<Treffpunkt> und passender Methode vergleiche (1 Punkt), Vergleich der Stadtteile (1 Punkt), Rückgabe dieses Ergebnisses, sobald es nicht 0 ist (1 Punkt), Namensvergleich nur bei gleichem Stadtteil (1 Punkt). Werden beide Ergebnisse einfach addiert, kann ein großer Unterschied im Namen einen kleinen Unterschied im Stadtteil überstimmen – die Rangfolge der Kriterien geht verloren.

db) Gib die Anweisungen an, mit denen ein Objekt Deines Vergleichers erzeugt und anschließend mit Deiner Methode aus cb) geprüft wird, ob die Liste treffpunkte (Typ List<Treffpunkt>) schon geordnet ist. Das Ergebnis soll in der Variablen geordnet stehen. (2 Punkte)

Vergleicher<Treffpunkt> v = new NachStadtteilUndName()     // 1 Punkt
Boolean geordnet = istSortiert(treffpunkte, v)             // 1 Punkt

Der Typ der Variablen darf auch NachStadtteilUndName sein. Für T wird beim Aufruf Treffpunkt eingesetzt.

dc) Die Liste treffpunkte enthält diese Einträge in dieser Reihenfolge:

Treffpunkte vor dem Ordnen
ID Stadtteil Name
8 Brackwede Bahnhof Brackwede
12 Mitte Kesselbrink
15 Mitte Alter Markt
21 Schildesche Obersee

Gib an, welchen Wert geordnet aus db) erhält und nach dem wievielten Vergleich istSortiert die Entscheidung trifft. Gib außerdem die Reihenfolge der IDs an, nachdem die Liste mit NachStadtteilUndName geordnet wurde. (2 Punkte)

  • geordnet ist false. Der erste Vergleich (Brackwede gegen Mitte) ist negativ, der zweite (beide Mitte, „Kesselbrink“ gegen „Alter Markt“) positiv – nach dem zweiten Vergleich gibt die Methode false zurück (1 Punkt).

  • Geordnete Reihenfolge: 8, 15, 12, 21 (1 Punkt).

e) Für volle Aktivitäten soll es eine Warteliste geben. Yusuf möchte sie generisch umsetzen, damit dieselbe Klasse später auch für die geplanten Interessengruppen (Warteliste von Benutzern) genutzt werden kann. Er hat die Klasse bereits entworfen:

UML-Klasse Warteliste mit Typparameter T, den Attributen elemente vom Typ List und maxLaenge sowie dem Konstruktor und den Methoden hinzufuegen, naechster, position und istLeer (mit KI erstellt)
  • Der Konstruktor legt die höchstens zulässige Anzahl von Einträgen fest und erzeugt eine leere Liste.

  • hinzufuegen hängt ein Element an das Ende an und gibt true zurück. Ist die Warteliste voll oder steht das Element schon darauf, wird nichts geändert und false zurückgegeben.

  • naechster gibt das Element zurück, das am längsten wartet, und entfernt es aus der Warteliste. Ist sie leer, wird null zurückgegeben.

  • position liefert den Platz eines Elements auf der Warteliste (der erste Platz ist 1) oder -1, wenn es nicht darauf steht. Objekte dürfen mit == verglichen werden.

ea) Erstelle den Konstruktor und die Methode hinzufuegen. (5 Punkte)

+ Warteliste(Integer maxLaenge) {
    this.maxLaenge = maxLaenge
    elemente = new List<T>()
}

+ Boolean hinzufuegen(T element) {
    if (elemente.size() >= maxLaenge) {
        return false
    }
    if (position(element) != -1) {
        return false
    }
    elemente.add(element)
    return true
}

Bewertung: Konstruktor mit Zuweisung und new List<T>() (2 Punkte), Prüfung „voll“ (1 Punkt), Prüfung „schon enthalten“ (1 Punkt, auch mit eigener Schleife), Hinzufügen und Rückgabe (1 Punkt). Wichtig: Im Code kommt kein konkreter Typ wie Teilnahme vor.

eb) Erstelle die Methode naechster. (3 Punkte)

+ T naechster() {
    if (elemente.size() == 0) {
        return null
    }
    T erster = elemente.get(0)
    elemente.remove(0)
    return erster
}

Leere Liste abgefangen (1 Punkt), erstes Element in einer Variablen vom Typ T gemerkt (1 Punkt), entfernt und zurückgegeben (1 Punkt). Wer zuerst entfernt und danach get(0) liest, gibt das falsche Element zurück.

ec) Erstelle die Methode position. (3 Punkte)

+ Integer position(T element) {
    for (Integer i = 0; i < elemente.size(); i++) {
        if (elemente.get(i) == element) {
            return i + 1
        }
    }
    return -1
}

Schleife über alle Elemente (1 Punkt), Vergleich und Rückgabe i + 1 (Platz beginnt bei 1, 1 Punkt), Rückgabe -1 nach der Schleife (1 Punkt).

Probe: Warteliste mit maxLaenge 2, hinzufuegen(lea) → true, nochmals hinzufuegen(lea) → false, hinzufuegen(malik) → true, hinzufuegen(kim) → false (voll); position(malik) → 2; naechster() → Lea, danach position(malik) → 1.

ed) Gib die Anweisung an, mit der für eine Aktivität eine Warteliste für Teilnahme-Objekte mit höchstens fünf Plätzen erzeugt und der Variablen warteliste zugewiesen wird. (1 Punkt)

Warteliste<Teilnahme> warteliste = new Warteliste<Teilnahme>(5)

(In Java auch new Warteliste<>(5) mit Diamant-Operator.)

f) Jonas probiert die Warteliste aus und erweitert sie.

fa) Für eine Interessengruppe schreibt er:

Warteliste<Benutzer> interessierte = new Warteliste<Benutzer>(3)
interessierte.hinzufuegen(benutzerKim)
interessierte.hinzufuegen(aktivitaet5)                         // Zeile 3
Benutzer b = (Benutzer) interessierte.naechster()              // Zeile 4

Beschreibe, wie der Compiler auf Zeile 3 reagiert, und erläutere, warum die Typumwandlung in Zeile 4 überflüssig ist. (3 Punkte)

  • Zeile 3 wird nicht übersetzt: Für interessierte ist T = Benutzer, hinzufuegen erwartet also einen Benutzer; eine Aktivitaet ist kein Benutzer (Typfehler zur Übersetzungszeit, in Java „incompatible types“) (2 Punkte).

  • naechster() hat den Rückgabetyp T, hier also Benutzer. Der Wert kann direkt einer Benutzer-Variablen zugewiesen werden; der Cast ist überflüssig (1 Punkt).

fb) Jonas möchte der Klasse Warteliste<T> eine Methode hinzufügen, die das Element mit der frühesten Anmeldung liefert:

+ T fruehesteAnmeldung() {
    T frueheste = elemente.get(0)
    for (Integer i = 1; i < elemente.size(); i++) {
        if (elemente.get(i).getAngemeldetAm() < frueheste.getAngemeldetAm()) {
            frueheste = elemente.get(i)
        }
    }
    return frueheste
}

Erläutere, warum sich die Klasse mit dieser Methode nicht übersetzen lässt, und beschreibe zwei Möglichkeiten, die Methode generisch umzusetzen. (4 Punkte)

  • Fehler: Der Typparameter T ist nicht eingeschränkt. Der Compiler weiß deshalb nicht, ob ein beliebiges T eine Methode getAngemeldetAm() besitzt – für Benutzer gibt es sie z. B. nicht. Auf Elementen vom Typ T dürfen nur Operationen verwendet werden, die für jeden Typ gelten (2 Punkte).

  • Möglichkeit 1: Den Vergleich als Parameter übergeben, z. B. T erstes(Vergleicher<T> v); im Algorithmus wird v.vergleiche(elemente.get(i), frueheste) < 0 geprüft (1 Punkt).

  • Möglichkeit 2: Den Typparameter einschränken, z. B. mit einer Schnittstelle Angemeldet mit getAngemeldetAm() und class Warteliste<T extends Angemeldet>; dann sind aber nur noch Klassen erlaubt, die diese Schnittstelle implementieren (1 Punkt).

  • Zusätzlicher Hinweis (ohne Punkte): Da hinzufuegen immer am Ende anhängt, steht die früheste Anmeldung ohnehin auf Platz 1. Außerdem fehlt die Behandlung der leeren Liste.

g) Nutzende sollen künftig nicht nur Aktivitäten, sondern auch Treffpunkte bewerten (z. B. Erreichbarkeit, Sauberkeit). Für die Startseite plant Yusuf eine Klasse, die die am besten bewerteten Einträge liefert:

interface Bewertbar {
    + Double getSterneSchnitt()
}

class Rangliste<T extends Bewertbar> {
    - List<T> eintraege
    + void hinzufuegen(T eintrag) { eintraege.add(eintrag) }
    + T beste() { … }
}

Die Klassen Aktivitaet und Treffpunkt implementieren Bewertbar, die Klasse Benutzer nicht.

ga) Erläutere die Bedeutung von T extends Bewertbar und gib an, ob die Deklarationen Rangliste<Treffpunkt> r1 und Rangliste<Benutzer> r2 zulässig sind. (3 Punkte)

  • T extends Bewertbar schränkt den Typparameter ein: Als Typargument sind nur Typen erlaubt, die die Schnittstelle Bewertbar implementieren (bzw. von ihr erben). Dafür darf die Klasse auf Elementen vom Typ T alle Methoden von Bewertbar aufrufen, hier getSterneSchnitt() (2 Punkte).

  • Rangliste<Treffpunkt> r1 ist zulässig, Rangliste<Benutzer> r2 wird vom Compiler abgelehnt, weil Benutzer nicht Bewertbar ist (1 Punkt).

gb) Erstelle die Methode beste(), die den Eintrag mit dem höchsten Sterne-Schnitt zurückgibt. Bei Gleichstand wird der zuerst hinzugefügte Eintrag geliefert, bei einer leeren Rangliste null. (4 Punkte)

+ T beste() {
    if (eintraege.size() == 0) {
        return null
    }
    T bester = eintraege.get(0)
    for (Integer i = 1; i < eintraege.size(); i++) {
        if (eintraege.get(i).getSterneSchnitt() > bester.getSterneSchnitt()) {
            bester = eintraege.get(i)
        }
    }
    return bester
}

Leere Liste (1 Punkt), Startwert mit dem ersten Eintrag in einer Variablen vom Typ T (1 Punkt), Vergleich über getSterneSchnitt() mit > (bei >= würde bei Gleichstand der spätere Eintrag geliefert) (1 Punkt), Rückgabe (1 Punkt).

h) Yusuf möchte die Klassen in der Architektur-Dokumentation als UML-Klassendiagramm (UML 2.5.1) festhalten. Zeichne die Template-Klassen Warteliste (mit Attributen und Methoden wie oben) und Rangliste (mit dem eingeschränkten Typparameter), die Schnittstelle Bewertbar mit den Klassen Aktivitaet und Treffpunkt sowie eine Klasse TeilnahmeWarteliste, die durch Bindung des Typparameters an Teilnahme entsteht. Attribute und Methoden von Aktivitaet und Treffpunkt musst Du nicht angeben. (5 Punkte)

Lösung: Template-Klasse Warteliste mit Parameterkasten T, gebundene Klasse TeilnahmeWarteliste mit «bind» T -> Teilnahme, Template-Klasse Rangliste mit T > Bewertbar, Schnittstelle Bewertbar, realisiert von Aktivitaet und Treffpunkt (mit KI erstellt)

Bewertung:

  • Warteliste mit gestricheltem Parameterkasten T an der rechten oberen Ecke, Attribute und Methoden (1 Punkt)

  • TeilnahmeWarteliste mit gestricheltem Pfeil zum Template, Schlüsselwort «bind» und T -> Teilnahme (1 Punkt; alternativ eine Klasse mit dem Namen Warteliste<T -> Teilnahme>)

  • Rangliste mit Parameterkasten T > Bewertbar (1 Punkt; die Schreibweise T extends Bewertbar ist als Java-Notation ebenfalls zu akzeptieren)

  • Schnittstelle Bewertbar mit «interface» und getSterneSchnitt(): Real (1 Punkt)

  • Realisierungen (gestrichelt, hohles Dreieck an Bewertbar) von Aktivitaet und Treffpunkt (1 Punkt)

Die «use»-Abhängigkeit von Rangliste zu Bewertbar ist optional.

i) Damit jede Aktivität ihre eigene Warteliste hat, verwaltet das Backend alle Wartelisten in einer Zuordnung:

Map<Integer, Warteliste<Teilnahme>> wartelisten     // Schlüssel: ID der Aktivität

Die Klasse Map<K, V> besitzt u. a. die Methode get(schluessel: K): V. Nenne die Typparameter der Klasse Map und die hier eingesetzten Typargumente, und gib die Anweisung an, mit der die Teilnahme teilnahmeLea auf die Warteliste der Aktivität mit der ID 5 gesetzt wird. (3 Punkte)

  • Typparameter: K (Schlüssel) und V (Wert) (1 Punkt).

  • Typargumente: K = Integer, V = Warteliste<Teilnahme> – das Typargument ist selbst eine gebundene generische Klasse (1 Punkt).

  • wartelisten.get(5).hinzufuegen(teilnahmeLea) (1 Punkt). get(5) liefert eine Warteliste<Teilnahme>, auf der hinzufuegen mit einer Teilnahme aufgerufen wird.

Summe Aufgabe 3.1: 61 Punkte


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Übungsaufgaben zu generischen Klassen und Typparametern” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/generische-klassen-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/programmierung/programmiergrundlagen. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 28.10.2026.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: