Die aktuellen Fragen zu diesem Kapitel haben wir beschränkt mit Rücksicht auf unsere Erstsemester, für die vorerst "einfache" Generics genügen mögen.
-
Wir nehmen aus dem Kapitel 12 das Unterkapitel 12.4 (Wildcards) raus.
-
Wir ignorieren die Verwendung von
extends
bei der Angabe von Typparametern.
Eine Klasse Container
soll im Konstruktor einen beliebigen Typ als Inhalt (content) aufnehmen können. Schreiben Sie den Code ohne Object
zu verwenden.
class Container<T> {
T content;
Container(T content) {
this.content = content;
}
}
jshell> new Container<Integer>(3) $20 ==> Container@17579e0f
Aus unerfindlichen Gründen bietet die Java-API keine Tupel-Klasse an. Wie würde so eine Klasse aussehen, die zwei Variablen von beliebigem Typ enthalten kann?
class Tupel<T,U> {
T car; // das ist ein historischer Name
U cdr; // das ist ein historischer Name
Tupel(T first, U second) {
car = first;
cdr = second;
}
}
Legen Sie eine neue ArrayList
an, die ausschließlich aus Ganzzahlen besteht.
new ArrayList<Integer>();
Deklarieren und initialisieren Sie eine Variable a
, die ausschließlich eine ArrayList
von boolschen Werten aufnehmen kann. Die Lösung muss so kurz wie möglich sein.
Entweder Sie deklarieren a
vom Typ ArrayList
:
ArrayList<Boolean> a = new ArrayList<>();
Oder, was Sie oft sehen, Sie nehmen das List
-Interface als Typ, der durch die ArrayList
implementiert wird.
List<Integer> a = new ArrayList<>();
Wie lautet die Syntax für eine generische Methode?
<T extends I> Rückgabetyp methodName(parameters) { ... }
Inwiefern hebelt die Definition <T> T giveMeWhatIWant() { … }
das Typsystem von Java aus?
Diese Methode muss eine Implementierung bieten, die für jeden Typ passen muss.
Wie sieht schematisch die Syntax einer generischen Klasse aus? Reduzieren Sie die Syntax auf das Notwendigste.
class Name<TypParameter, ...> { ... }
class A<T> { void foo(T x) {} } A myA = new A();
Kann man das schreiben? Welcher Typ wird für den Typparameter T
eingesetzt?
Der allgemeinste Typ hier, der implizit eingesetzt wird, ist Object
. Aber: Das ist kein guter Programmierstil.
class Foo<T> { int getLength(T value) { return value.length(); } } Foo<String> f = new Foo<>(); f.getLength("abc");
Oh Schmerz! Weswegen?
Man kann nicht davon ausgehen, dass value
, dessen Typ über T
frei gewählt werden kann, eine length
-Method hat.
class Bar<Blubber> { Blubber x; }
Problem?
Nein, kein Problem. Es ist unüblich, lange Namen für Typparameter zu wählen. Per Konvention verwendet man nur einzelne Großbuchstaben.
Man kann eine Klasse als MyClass<T extends Number>
deklarieren, ist auch MyClass<T implements AutoCloseable>
erlaubt?
Das implements
ist in der Syntax nicht vorgesehen, ist nicht erlaubt.
class ICanHazGenerics<E extends Comparable> {}
Und schon gibt’s was auf die Finger. Was ist der Grund?
Man sollte den Typ für Comparable<???>
angeben.
class A<T extends B> {}
Kann man A<B> value = new A<B>();
schreiben? Gilt also B extends B
?
Die Klasse B
als T
kann das, was B
kann, das meint <T extends B>
.
List<? extends Number> lst = new ArrayList<>(); lst.add(new Integer(8));
Die zweite Zeile produziert einen Fehler. Können Sie sich vorstellen, warum man einer List<? extends Number>
keinen Integer
hinzufügen kann?
Man könnte mal einen Integer
der Liste hinzufügen, mal einen Double
. Der Compiler kann diese Entscheidung nicht auflösen.