Generics
IntBox
public class IntBox {
private int content;
public void set(int content) {
this.content = content;
}
public int get() {
return content;
}
}
IntBox intBox = new IntBox();
int i = intBox.get();
DoubleBox
public class DoubleBox {
private double content;
public void set(double content) {
this.content = content;
}
public double get() {
return content;
}
}
DoubleBox doubleBox = new DoubleBox();
double d = doubleBox.get();
Box
public class Box {
private Object content;
public void set(Object content) {
this.content = content;
}
public Object get() {
return content;
}
}
Box box = new Box();
Object d = box.get();
Box box = new Box();
box.set(42);
int i = box.get(); 🚫
int i = (int) box.get();
- Keine Typchecks zur Compilezeit
Box<T>
public class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}
Box<Integer> intBox = new Box<>();
intBox.set(42);
int i = intBox.get();
intBox.set(3.14); 🚫
Box<Double> doubleBox = new Box<>();
doubleBox.set(3.14);
Generell
class Name<T, E, K, V, S, U>
extends X<T> implements Y<T, E>, Z { }
- Parameter: Übergabe Wert
foo(value) - Typparameter: Übergabe Typ
Foo<Type> - Typparameter wird beim Erzeugen gesetzt
new Box<Integer>(3);
new Box<Double>();
Falls der Typ "klar" ist, kann auch <> stehen
Box<String> box = new Box<>();
Box< Box<String> > boxBox = new Box<>();
Implementierung
public class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
}
wird beim Kompilieren zu
public class Box {
private Object content;
public void set(Object content) {
this.content = content;
}
}
Generische Methoden
modifier... <T, U, ...> returntyp name(params...)
class Utils {
public static <T> void foo(T t) { }
}
Meist werden Typargumente automatisch ergänzt (Type inference)
Utils.foo(42);
Konsequenzen
Note wird schlechter bei
catch Exceptionreturn nullfoo(null)- Raw Types in Abgabe
- IntelliJ unterlegt Box färbig
- IntelliJ Problems
- IntelliJ Analyze -> Inspect Code
Bounded Types
public class NumberBox<T extends Number> {
private T content;
public NumberBox(T content) {
this.content = content;
}
public int intValue() {
return content.intValue();
}
}
new NumberBox<>(3);
new NumberBox<>(3.1415);
new NumberBox<>("legit"); 🚫
extends steht hier auch für Interfaces
Vererbung
Integer i = 42;
Number number = i; ✔️
Object object = i; ✔️
Box<Number> box = new Box<>();
box.set(10);
box.set(3.1415);
Box<Number> box = new Box<Number>();
box = new Box<Integer>(); 🚫


Box<Integer> integerBox = new Box<>();
Box<Number> numberBox = new Box<>();
numberBox = integerBox; 🚫
ansonsten
numberBox.set(3.1415);
int i = integerBox.get();
? extends - Wildcards
Box<Number> box = new Box<>();
box = new Box<Integer>(); 🚫
Box<? extends Number> box;
box = new Box<Number>();
box = new Box<Integer>();
box = new Box<Double>();
box.set(3.1415); 🚫 box könnte Box<Integer> sein
double d = box.get(); 🚫 box könnte Box<LongLong> sein
Number number = box.get(); ✔️
Box<?> box = new Box<AnyClass>();️
? super
Box<? super Integer> box;
box = new Box<Integer>();
box = new Box<Number>();
box = new Box<Object>();
box.set(number); 🚫 box könnte Box<Integer> sein
box.set(42); ✔️
int i = box.get(); 🚫 box könnte Box<Number> sein
Verwendung
extends für Parameter
static int intValue(Box<Number> box) {
return box.get().intValue();
}
intValue(new Box<Number>()); ✔️
intValue(new Box<Integer>()); 🚫
könnte man verbessern zu
static int intValue(Box<? extends Number> box) {
return box.get().intValue();
}
intValue(new Box<Number>()); ✔️
intValue(new Box<Integer>()); ✔️
Einschränkungen
-
Keine primitiven Typen als Typargument
Box<int> box; 🚫 -
Keine Konstruktoraufrufe für Typparameter
new T(); 🚫 -
Keine statischen Typparameter - Referenzen
class Foo<T> { static T t; 🚫 }
-
Keine generischen Arrays erzeugen
static <T> void foo() { T[] array; ✔️ array = new T[1]; 🚫 } -
Keine Arrays parametrisierter Typen
static void foo() { Box<Integer>[] array; ✔️ array = new Box<Integer>[1]; 🚫 } -
Typparameter - varargs sind ok, solang die Methode nicht für ein
Object[]aufgerufen wird@SafeVarargs static <T> void foo(T... ts) { }