Generics
Type Parameter
<T>
is Type parameter
public class Printer <T> {
T val;
}
Bounded Generic
<T extends Animal>
is bounded generic
public class Printer <T extends Animal> {
T val;
}
Animal
can be a class or Interface. Useextends
for interfaces. No such thing as<T implements Animal>
Multiple Bounded Generic
<T extends Animal & Serializable>
is multiple bounded generic
public class Printer <T extends Animal & Serializable> {
T val;
}
- With multiple bounds there can be atmost 1 class
- The class should be the 1st entry.
<T extends Serializable & Animal>
, listingAnimal
class as the second item would lead to compilation error
Recursive Type
class Fruit <T extends Fruit<T>>
is recursive type
class Fruit <T extends Fruit<T>> implements Comparable<T> {
T size;
@override public int compareTo(T other) {
return size.compareTo(other.getSize()) // .getSize() is available because T extends Fruit<T>
}
}
-
A recursive type is one that includes a function that uses that type itself as a type for some argument or its return value.
-
Explained beautifuly in this stack overflow answer.
Generic Method
public static <T> void print(T toPrint) {
System.out.println(toPrint);
}
- Type Parameter should be specified within diamond brackets before the return type.
Wildcard (?) in Generic Method
Call to print
will fail as it expects a List<Object>
which is not the same as List<Animal>
public static void main(String args[]) {
List<Animal> animals = Arrays.asList(new Cat(), new Dog());
print(animals)
}
public static void print(List<Object> toPrint) {
for (Object obj: toPrint) {
System.out.println(toPrint);
}
}
We can use the wildcard ? to specify list of unknown
type List<?>
public static void main(String args[]) {
List<Animal> animals = Arrays.asList(new Cat(), new Dog());
print(animals)
}
public static void print(List<?> toPrint) { // Compiler can assume ? is atleast of base type Object.
for (Object obj: toPrint) {
System.out.println(toPrint);
}
}
Bounded Wildcard in Generic Method
<? extends Animal>
is a upper bounded wildcard
public static void main(String args[]) {
List<Animal> animals = Arrays.asList(new Cat(), new Dog());
print(animals)
}
public static void print(List<? extends Animal> toPrint) { // You can pass the type and subtypes - List<Animal>, List<Cat>, List<Dog> but not List<Object>
for (Object obj: toPrint) {
System.out.println(toPrint.toPrettyString()); // Gives access to .toPrettyString() method in Animal
}
toPrint.add(new Cat()) // Compile error: Cannot infer what type list is, could be a List<Dog>
}
<? super Cat>
is a lower bounded wildcard
public static void main(String args[]) {
List<Animal> animals = Arrays.asList(new Cat(), new Dog());
addCat(animals) // It works, I should be able to add a Cat intop a list of Animals
}
public static void addCat(List<? super Cat> animals) { // You can pass the type and supertypes - List<Cat>, List<Animal>, List<Object>. You cant pass a List<Dog>
toPrint.add(new Cat())
}