Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generic method boundaries

Tags:

java

generics

What is the difference in following 2 lines?

public static <T extends Comparable<? super T>> int methodX(List<T> data)
public static <T> int methodX(List<? extends Comparable<? super T>> data)
like image 633
Margus Avatar asked Jul 30 '11 13:07

Margus


1 Answers

Your first option is a "stricter" parametrisation. Meaning, you're defining the class T with a bunch of restrictions, and then use it later on with List. In your second method, the parameter class T is generic with no conditions, and the Lists class parameter is defined in terms of the parameter T.

The second way is syntactically different as well, with a ? instead of the first option's T, because in the parameter definition you aren't defining the type parameter T but rather using it, so the second method cannot be as specific.

The practical difference that comes out of this is one of inheritance. Your first method needs to be a type that is comparable to a super class of itself, whereas the second type need only be comparable to an unconditional/unrelated T:

public class Person implements Comparable<Number> {
    @Override
    public int compareTo(Number o) {
        return 0;
    }
    public static <T extends Comparable<? super T>> int methodX(List<T> data) {
            return 0;
    }
    public static <T> int methodY(List<? extends Comparable<? super T>> data) {
            return 0;
    }
    public static void main(String[] args) {
        methodX(new ArrayList<Person>()); // stricter ==> compilation error
        methodY<Object>(new ArrayList<Person>());
    }
}

If you change the Comparable of Person to be able to compare Object or Person (the inheritance tree of the base class) then methodX will also work.

like image 150
davin Avatar answered Oct 05 '22 19:10

davin