0

Where should one use extends, where should one use super, and where is it inappropriate to use a wildcard at all?

Is their any principle or rule or it all related to one's own understanding and scope of application.

Like currently i need only two numbers to add in list so i will used,

 public List<Integer> addToNewList(integerList  , Integer element){
   integerList.add(element);
   return integerList;
}

But Later on Scope of my application increase and now it require all numbers, so make it generic for maximum support. ex :

public <T extends Number> List<T> addToList(List<? extends T> genericList , T element){
   genericList.add(element);
   return genericList;
}

In short i just want to know, when should one use these wildcards and when not ?

Prateek
  • 12,014
  • 12
  • 60
  • 81
  • possible duplicate of [When to use generic methods and when to use wild-card?](http://stackoverflow.com/questions/18176594/when-to-use-generic-methods-and-when-to-use-wild-card) – Rohit Jain Sep 03 '13 at 06:22
  • 1
    This [link](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html) gives a good and comprehensive overview of the generics in java – Jan Piel Sep 03 '13 at 06:38

2 Answers2

4

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

Community
  • 1
  • 1
Prateek
  • 12,014
  • 12
  • 60
  • 81
2

You should use them when they make sense...

In your instance you said you had to refactor the code to change the generic type to Number from integer due to application evolution. This is perfectly OK for me. It's nearly impossible to expect all the ways an application may evolve. Writing code to handle a 'may in the future' scenario is futile until it approaches that time in the future since it may not arrive there at all.

That being said you should try to design your APIs to the least restricting type the functionality of your function can perform well. Unless of course it will require considerably more effort and current functionality have no use for the flexibility being offered.

Thihara
  • 7,031
  • 2
  • 29
  • 56