Java: Generics Typvariablen
Willemers Informatik-Ecke
Object und Wrapper Java Java Collection Framework

Manchmal möchte man Klassen schaffen, die mit unterschiedlichen Typen umgehen können. Dazu gehören beispielsweise Container wie die Java-Collection. Betrachten wir eine sehr einfache Klasse Paar. Sie soll ein ganzzahliges Variablenpaar aufnehmen.
class Paar {
    int i1, i2;
    public Paar(int i1, int i2) {
        this.i1 = i1; this.i2 = i2;
    }
}
Sollten wir ein weiteres Paar mit Strings benötigen, müssten wir eine neue Klasse schaffen. Dummerweise dürften wir den Klassennamen nicht wiederverwenden, auch wenn er eigentlich auch für Stringt sehr passend ist.
class StringPaar {
    String i1, i2;
    public StringPaar(String i1, String i2) {
        this.i1 = i1; this.i2 = i2;
    }
}
Aber da wir wissen, dass die Klasse Object die Basisklasse aller Klasse ist, können wir die Elemente als Object definieren. Und schon können wir alle beliebigen Typen paarweise ablegen.
class Paar {
    Object i1, i2;
    public Paar(Object i1, Object i2) {
        this.i1 = i1; this.i2 = i2;
    }
}
Im Testlauf funktioniert nun beides, Zahlen und auch Strings:
public class PaarTest {
    public static void main(String[] args) {
        Paar paar = new Paar(1,3);
        Paar str = new Paar("Laurel", "Hardy");
    }
}
Leider funktioniert nun aber auch dies:
Paar nichtgut = new Paar("Pferd", 3.14159);

Typsicherheit durch Typvariablen

Java ermöglicht es, die Klasse Paar so zu definieren, dass beim Anlegen eines Objekts festgelegt wird, mit welche Klassentypen die Klasse Paar akzeptiert. Im Gegensatz zur Verwendung von Object entsteht dadurch eine Typsicherheit. Dazu verwendet man Generics mit Typvariablen.

Syntaktisch wird dem Klassenname in spitzen Klammern (Kleiner- und Größerzeichen) eine Variable mit einer Typvariablen gekennzeichnet. Innerhalb der Klasse wird dieser Name anstelle des Typen verwendet. Man verwendet dazu einen einzelnen Großbuchstaben, meist T. Das ist aber lediglich Konvention.

Wir können also die Klasse Paar übernehmen und statt Object ein T verwenden und dieses am Klassennamen mit spitzen Klammern einfügen.

class Paar<T> {
    T i1, i2;
    public Paar(T i1, T i2) {
        this.i1 = i1; this.i2 = i2;
    }
}
Tatsächlich funktionieren alle Aufrufe in PaarTest nach wie vor. Um eine Typsicherheit zu erlangen, muss der Typ bei der Instanziierung angegeben werden.

public class PaarTest {
    public static void main(String[] args) {
        Paar<Integer> paar = new Paar<Integer>(1,3);
        Paar<String> str = new Paar<>("haa", "huh");
        Paar<String> nichtgut = new Paar("Pferd", 3.14159);
    }
}

Typvorgaben durch Interfaces

Die Möglichkeiten einer generischen Klasse sind oft beschränkt, da nur Methoden erlaubt sind, die allen Klassen gemein sind. Beispielsweise gibt es bei der folgenden Klasse, die eine Minimumfunktion zur Verfügung stellen will, Schwierigkeiten, da Klassen das Kleinerzeichen nicht kennen.
public class Minimum {
    boolean min(T a, T b) {
        boolean kleiner = false;
        if (a < b) {  // Compilerfehler, da Klassen Kleiner nicht kennen
            kleiner = true;
        }
        return kleiner;
    }
}
Stattdessen kann eine Methode less verwendet werden, die allerdings den Nachteil hat, dass auch sie den meisten Klassen nicht bekannt ist. Allerdings kann man mit einem Interface erzwingen, dass alle Klassen, die Minimum verwenden, eine Methode less implementieren. Im ersten Schritt wird die Abhängigkeit im Klassenkopf deklariert.
public class Minimum<T extends Comparable<T>> {
    boolean min(T a, T b) {
        boolean kleiner = true;
        if (a.compareTo(b)>0) {
            kleiner = false;
        }
        return kleiner;
    }
}
Das Interface Comparable wird sowohl von String als auch von Integer implementiert. Die Aufrufe würden folgendermaßen aussehen:
Minimum<String> m = new Minimum<>();
System.out.println(m.min("C",  "B"));
Minimum<Integer> n = new Minimum<>();
System.out.println(n.min(1, 3));
Eigene Klassen müssten Comparable implementieren und dazu die Methode compareTo definieren, um die Klasse Minimum nutzen zu können.

Video


Object und Wrapper Java Java Collection Framework