tags:

views:

341

answers:

4

Hi ,

Please any one give me a good example for covariance and contravariance in Java . Why we go for this .

Thx

+2  A: 

You find some info about it on wikipedia:

http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Java

Emiswelt
thx .. But I cant get the detailed information .Why covariance/contravariance came into picture ?
JavaUser
+1  A: 

Look at the Liskov substitution principle. In effect, if class B extends class A then you should be able to use a B whenever an A is required.

extraneon
better point out ..cool!!!
JavaUser
+7  A: 

Covariance:

class Super {
  Object getSomething(){}
}
class Sub extends Super {
  String getSomething() {}
}

Sub#getSomething is covariant because it returns a subclass of the return type of Super#getSomething (but fullfills the contract of Super.getSomething())

Contravariance

class Super{
  void doSomething(String parameter)
}
class Sub extends Super{
  void doSomething(Object parameter)
}

Sub#doSomething is contravariant because it takes a parameter of a superclass of the parameter of Super#doSomething (but, again, fullfills the contract of Super#doSomething)

Generics

This is also possible for Generics:

List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;

You can now access all methods of covariantList that doesn't take a generic parameter (as it must be something "extends Object"), but getters will work fine (as the returned object will always be of type "Object")

The opposite is true for contravariantList: You can access all methods with generic parameters (you know it must be a superclass of "String", so you can always pass one), but no getters (The returned type may be of any other supertype of String)

Hardcoded
+2  A: 

Co-variance: Iterable and Iterator. It almost always makes sense to define a co-variant Iterable or Iterator. Iterator<? extends T> can be used just as Iterator<T> - the only place where the type parameter appears is the return type from the next method, so it can be safely up-cast to T. But if you have S extends T, you can also assign Iterator<S> to a variable of type Iterator<? extends T>. For example if you are defining a find method:

boolean find(Iterable<Object> where, Object what)

you won't be able to call it with List<Integer> and 5, so it's better defined as

boolean find(Iterable<?> where, Object what)

Contra-variance: Comparator. It almost always makes sense to use Comparator<? super T>, because it can be used just as Comparator<T>. The type parameter appears only as the compare method parameter type, so T can be safely passed to it. For example if you have a DateComparator extends Comparator<java.util.Date> { ... } and you want to sort a List<java.sql.Date> with that comparator (java.sql.Date is a sub-class of java.util.Date), you can do with:

<T> void sort(List<T> what, Comparator<? super T> how)

but not with

<T> void sort(List<T> what, Comparator<T> how)
Yardena