Generics

        GENERICS
Generics are described as follows:
• Provides compile-time type safety
• Eliminates the need for casts


• It improve the Java performance, by eliminating the "instance of" operator.
The Java Generics features were added to the Java language from Java 5. Generics add a way to specify concrete types to general purpose classes and methods that operated on Object before.
Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods or, with a single class declaration, a set of related types, respectively.
Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.
Using Java Generic concept we might write a generic method for sorting an array of objects, then invoke the generic method with Integer arrays, Double arrays, String arrays and so on, to sort the array elements.
Before Generics
ArrayList list = new ArrayList();
list.add(0, new Integer(42));
int total = ((Integer)list.get(0)).intValue();
List
List list = new ArrayList();
list.add(new Integer(2));
list.add("a String");
Integer integer = (Integer) list.get(0);
String string = (String) list.get(1);
With Java's Generics features you can set the type of the collection to limit what kind of objects can be inserted into the collection. Additionally, you don't have to cast the values you obtain from the collection.
After Generics
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = list.get(0).intValue();
List<String> strings = new ArrayList<String>();
strings.add("a String");
String aString = strings.get(0);
List<String> strings = new ArrayList<String>();
//... add String instances to the strings list...
for(String aString : strings)
{ System.out.println(aString); }
Container objects are objects that contain other objects. Before Generics were introduced there was no way to ensure that a container object contains only one type of objects. When an object was added to a container, it was automatically cast to Java object. When it was taken out an explicit cast was needed. Normally an explicit cast is checked by the compiler.
String st = "This is a String";
 Integer integer = (Integer) st;  // --- Compilation Error
But in the case of container classes, the compiler was not able to catch an invalid type casting.
1 Collection collString = new ArrayList();
2 collString.add( "This is a String" );
...
3 Integer integer = (Integer) collString.get(0);  // --- No Compilation Error; RunTime CastException
Just looking at line 3, we do not know what type of objects collString contains. If that contains Integers then the code is fine.
The below code using Generic:
Collection<String> collString = newArrayList<String>();
collString.add( "This is a String" );
...
Integer integer = (Integer) collString.get(0);  // --- Compilation Error
collString is a container object, that can contain only String objects, nothing else, so when we get out an element it can be casted only to class that normally a String can be casted.
With Generics, Java strict type checking can be extended to container objects. Using Generics with container classes, gives an impression that a new container type is created, with each different type parameter.
Before Generics:
Collection collCustomer = new ArrayList();
collCustomer.add(new Customer() );
...
Collection collObject = collCustomer;  // --- No problem, both collObject and collCustomer have the same type
With generics:
Collection<Customer> collCustomer = new ArrayList<Customer>();
collCustomer.add(new Customer() );
...
Collection<Object> collObject = collCustomer;  // --- Compilation Error
Both collObject and collCustomer have the same type, BUT it is against the Generic rule, that is collCustomer can contain only Customer objects, and collObject can contain only Object object. So there is an additional check to the normal type checking, the type of the parameter type has to be matched too.
If we write <? extends Object> instead of T, then we can pass any kind of objects, regardles of their type:
List<? extends Object> list3 = makeAList("One", 10, new StringBuffer(), new LinkedList());
Note: the number 10 in the above code will be converted (autoboxed) to Integer.
Wildcard Types
The wildcard type is represented by the character <?>, and pronounced Unknown, or Any-Type. This Unknown type matches anything, if it is used only by itself. Any-Type can be express also by <? extends Object>. Any-Type includes Interfaces, not only Classes.
So now we can define a collection whose element type matches anything. See below:
Collection<?>collUnknown;
Note that we cannot add anything to this collection. We can only take out elements of type Object from it. So what is the use of this variable if we cannot add anything to the collection it represents? The use of this new construct will be clear when you want to create a generic method that takes any collection.
Public static void printElements( Collection<?>anycoll )
{
   Iterator<?>iter = coll.iterator();
While ( iter.hasNext() )
   {
System.out.print( iter.next() );
   }   
}

Wildcard for a specific type of classes 
"<? extends ClassName>"specifies a restriction on the types of classes that may used.
For example, to create a collection that may only contain "Serializable" objects, specify:
Collection<? extends Serializable>serColl = new ArrayList<String>();
The above code is valid because, the String class is serializable. Use of a class that is not serializable would cause a compilation error.
The following collection can only contain objects that extend the class Animal.
Class Dog extends Animal
{
 ...
}
...
// --- Create "Animal Collection" variable ---
Collection<? extends Animal>animalColl = new ArrayList<Dog>();

"<? super ClassName>"specifies a restriction on the types of classes that may be used.
For example, to declare a Comparator that can compare Dogs, you use
Comparator<? super Dog>myComparator;
Now suppose you define a comparator that can compare Animals:
Class AnimalComparatorimplements Comparator<Animal>
{
  int compare(Animal a, Animal b) { //...
  }
}
Since Dogs are Animals, you can use this comparator to compare Dogs also. Comparators for any superclass of Dog can also compare Dog; but comparators for any strict subclass cannot.
Comparator<Animal>myAnimalComparator = new AnimalComparator();

static int compareTwoDogs(Comparator<? super Dog> comp, Dog dog1, Dog dog2) {
  return comp.compare(dog1, dog2);
}
The above code is valid because, the Animal class is a supertype of the Dog class. Use of a class that is not a supertype would cause a compilation error.