Eg.
List<String> stringsList = new ArrayList<String>();
stringsList.add("hello");// Ok
stringsList.add("salut"); // Ok
stringsList.add(new Integer(2)); // This won't compile: type safety
Backward compatibility.
Because generics have been introduced since Java 5, you can use, for example, a Collection without specifying a type. The code will compile and run, with however a compilation warning. Eg.
List mixedList = new ArrayList<String>(); // This is legal!
mixedList.add("hello");
mixedList.add("salut");
mixedList.add(new Integer(2)); // This time it will compile
for(Object anElement : mixedList){
System.out.println("- element: "+anElement.toString());
}
During the compilation, the following warning is displayed: "Note: TestGeneric.java uses unchecked or unsafe operations."
But the code compiles and runs fine, the output is:
- element: hello
- element: salut
- element: 2
You can also pass a typed Collection to a non typed collection as argument: Eg.
// Non typed Collection
public static void test(List mixedList){
mixedList.add(new Integer(2)); // Ok
}
...
List mixedList = new ArrayList<String>();
mixedList.add("hello");
mixedList.add("salut");
test(mixedList);
for(Object anElement : mixedList){
System.out.println("- element: "+anElement.toString());
}
During the compilation, a warning is displayed: "Note: TestGeneric.java uses unchecked or unsafe operations."
Output:
- element: hello
- element: salut
- element: 2
Polymorphic declaration.
Note that with generics you can not use a polymorphic declaration. Eg.
class Animal {}
class Dog extends Animal {}
List<Animal>animals = new ArrayList<Animal>(); // Ok
List<Animal> animals = new ArrayList<Dog>(); // This won't compile: "incompatible types"
Animal[] animals = new Dog[3]; // This works with array but not with generics
Note that this rule does not avoid you adding a 'Dog' in a list of 'Animal':
List<Animal>animals = new ArrayList<Animal>(); // Ok animals.add(new Animal()); // Ok animals.add(new Dog()); // Ok, as 'Dog' IS-AN 'Animal'
Usage of wildcard '?' with a collection
If you use generic wildcard '?' with a collection then the collection can be accessed but not modified.
Example of <? extends [className]> :
public static void testWildcardExtends(List<? extends Animal> animalsList){
animalsList.get(0); // Ok
animalsList.add(new Dog()); // This won't compile: "cannot find symbol" => you are not allowed to modify this collection because of the usage of wildcard '?'
}
...
List<Dog> dogsList = new ArrayList<Dog>();
dogsList.add(new Dog());
testWildcardExtends(dogsList); // Ok as 'Dog' is an 'Animal'
Example of <? super [className]> :
public static void testWildcardSuper(List<? super Dog> animalsList){
animalsList.get(0); // Ok
animalsList.add(new Animal()); // This won't compile: "cannot find symbol" => you are not allowed to modify this collection because of the usage of wildcard '?'
}
...
List<Animal> animalsList = new ArrayList<Animal>();
animalsList.add(new Animal());
testWildcardSuper(animalsList); // Ok as 'Animal' is a superclass of 'Dog'
Example of <?> :
public static void testWildcardOnly(List<?> aList){
aList.get(0); // Ok
aList.add(new Animal()); // This won't compile: "cannot find symbol" => you are not allowed to modify this collection because of the usage of wildcard '?'
}
...
List<Animal> animalsList = new ArrayList<Animal>();
animalsList.add(new Animal());
testWildcardOnly(animalsList); // Ok, you can pass any type of collection
List<Integer> intsList = new ArrayList<Integer>();
intsList.add(new Integer(87));
testWildcardOnly(intsList); // Ok, you can pass any type of collection
You can use wildcare in declaration as well. But the limitation is the same: the collection can not be modified:
List<?> aList = new ArrayList<Animal>(); // Ok List<? extends Animal> dogList = new ArrayList<Dog>(); // Ok List<? super Dog> animalList = new ArrayList<Animal>(); // Ok
Write a generic class
Eg.
class MyGenericClass <AType> { // Note that you can also use wildcare ? or many types like <AType1, AType2>, or <? extends AType>, or <? super AType>
private List<AType> typesList;
MyGenericClass(){
this.typesList = new ArrayList<AType>();
}
public void add(AType aType){
this.typesList.add(aType);
}
public String toString(){
String toReturn = "";
for(AType anElement : this.typesList){
toReturn += "\n- element: "+anElement;
}
return toReturn;
}
}
Let's use the generic class:
MyGenericClass<String> aGeneric = new MyGenericClass<String>(); // "AType" is now a "String"
aGeneric.add("hello");
aGeneric.add("salut");
System.out.println("Elements: "+aGeneric.toString());
Output:Elements:
- element: hello
- element: salut
Write a generic method in a non generic class
You can declare one or many generic methods in a non generic class. Eg.
class MyClass { // This is a simple class (non generic)
public <AType> void printType(AType aType) { // You can notice that the generic declaration <AType> is just before the method's return type void;
System.out.println("Element: "+aType); // As for a generic class, you can also use wildcare or many types like <AType1, AType2>, or <? extends AType>, or <? super AType>
}
public void doSomething() { // Non generic method
}
}
Let's use the generic method:
MyClass myClass = new MyClass(); myClass.printType(new Integer(40)); // AType is now an IntegerOutput:
Element: 40