I understood the when to use and when not to use and there is one awesome principle i found in one book :
The Get and Put Principle: use an extends wildcard when you only get
values out of a structure, use a super wildcard when you only put
values into a structure, and don’t use a wildcard when you both get
and put.
Here is a method that takes a collection of numbers, converts each to a double, and sums them up:
public static double sum(Collection<? extends Number> nums) {
double s = 0.0;
for (Number num : nums) s += num.doubleValue();
return s;
}
Since this uses extends, all of the following calls are legal:
List<Integer>ints = Arrays.asList(1,2,3);
assert sum(ints) == 6.0;
List<Double>doubles = Arrays.asList(2.78,3.14);
assert sum(doubles) == 5.92;
List<Number>nums = Arrays.<Number>asList(1,2,2.78,3.14);
assert sum(nums) == 8.92;
The first two calls would not be legal if extends was not used.
EXCEPTION : You cannot put anything into a type declared with an extends wildcard—except for the value null, which belongs to every reference type.
Whenever you use the add method, you put values into a structure, so use a super
wildcard. Here is a method that takes a collection of numbers and an integer n, and
puts the first n integers, starting from zero, into the collection:
public static void count(Collection<? super Integer> ints, int n) {
for (int i = 0; i < n; i++) ints.add(i);
}
Since this uses super, all of the following calls are legal:
List<Integer>ints = new ArrayList<Integer>();
count(ints, 5);
assert ints.toString().equals("[0, 1, 2, 3, 4]");
List<Number>nums = new ArrayList<Number>();
count(nums, 5); nums.add(5.0);
assert nums.toString().equals("[0, 1, 2, 3, 4, 5.0]");
List<Object>objs = new ArrayList<Object>();
count(objs, 5); objs.add("five");
assert objs.toString().equals("[0, 1, 2, 3, 4, five]");
The last two calls would not be legal if super was not used.
EXCEPTION : you cannot get anything out from a type declared with a super wildcard—
except for a value of type Object, which is a super type of every reference type.
This principle is also explained in following question Get and Put rule