The question is published on by Tutorial Guruji team.
While I was trying to solve exercise from generics tutorial Q&A My answers were slightly different
My Answers
public static <T extends Comparable<? super T>> T max(List<? extends T> list, int begin, int end) //Option1 public static <T extends Comparable<T>> T max(List<? extends T> list, int begin, int end) //Option2
from quoted answer below
So My question is
Option1 :Would it make any difference if
T extends Object & Comparable<? super T>
is replaced withT extends Comparable<? super T>
. Isn’textends Object
implicit ?Option2 :Would it make any difference if
Comparable<? super T>
is replaced withComparable<T>
? if so How ?Eclipse code completion creates local variable
List<? extends Comparable<? super Comparable<? super T>>> list;
on Ctrl+1max(list, 1, 10);
which is bit lengthy. How to Define a classes (hierarchy) that extendsComparable<? super T>
, create list and add instances to the list and invoke below method ? Basically I want to know how to invokemax()
after adding class instancesA or B
into a list whereclass B extends A
Write a generic method to find the maximal element in the range [begin, end) of a list.
Answer:
import java.util.*; public final class Algorithm { public static <T extends Object & Comparable<? super T>> T max(List<? extends T> list, int begin, int end) { T maxElem = list.get(begin); for (++begin; begin < end; ++begin) if (maxElem.compareTo(list.get(begin)) < 0) maxElem = list.get(begin); return maxElem; } }
Answer
Would it make any difference if
Comparable<? super T>
is replaced withComparable<T>
? if so How ?
Remember that Comparables are always consumers, i.e., a Comparable<T>
consumes T
instances, so it should always be preferrable to use Comparable<? super T>
instead of Comparable<T>
(Quoting – PECS). It would make difference in case you are comparing a type whose super class implements a Comparable<SuperType>
. Consider the following code:
class Parent implements Comparable<Parent> { protected String name; @Override public int compareTo(Parent o) { return this.name.compareTo(o.name); } } class Child extends Parent { public Child(String name) { this.name = name; } }
Now if you give your type parameter as T extends Comparable<T>
, you won’t be able to call that method for List<Child>
, as Child does not implement Comparable<Child>
but Comparable<Parent>
:
public static <T extends Comparable<T>> T max(List<? extends T> list, int begin, int end) { ... } public static void main(String[] args) { List<Child> list = new ArrayList<Child>(); max(list, 0, 2); // Error with current method. Child does not implement Comparable<Child> }
Hence the type parameter bounds should be T extends Comparable<? super T>
.
Note that, you can’t change your Child class to:
class Child extends Parent implements Comparable<Child>
because in that case, Child class would extend from different instantiation of same generic type, which is not allowed.
Would it make any difference if
T extends Object & Comparable<? super T>
is replaced withT extends Comparable<? super T>
. Isn’t extends Object implicit ?
Well, there is a difference between the two bounds. In the 1st bound, the erasure of the type parameter is Object
, whereas in the 2nd bound, the erasure is Comparable
.
So, without Object
bound, your code will compile to:
public static Comparable max(List list, int begin, int end)
The issue might come when you are generifying the legacy non-generic code. It’s neccessary to give Object
also as upper bound to avoid breaking the Byte Code compatibility. You can read more about it on this link: Angelika Langer – Programming Idioms