What is <? super T> syntax?

Java

Java Problem Overview


I'm having trouble understanding the following syntax:

public class SortedList< T extends Comparable< ? super T> > extends LinkedList< T >

I see that class SortedList extends LinkedList. I just don't know what

T extends Comparable< ? super T>

means.

My understanding of it so far is that type T must be a type that implements Comparable...but what is < ? super T >?

Java Solutions


Solution 1 - Java

super in Generics is the opposite of extends. Instead of saying the comparable's generic type has to be a subclass of T, it is saying it has to be a superclass of T. The distinction is important because extends tells you what you can get out of a class (you get at least this, perhaps a subclass). super tells you what you can put into the class (at most this, perhaps a superclass).

In this specific case, what it is saying is that the type has to implement comparable of itself or its superclass. So consider java.util.Date. It implements Comparable<Date>. But what about java.sql.Date? It implements Comparable<java.util.Date> as well.

Without the super signature, SortedList would not be able accept the type of java.sql.Date, because it doesn't implement a Comparable of itself, but rather of a super class of itself.

Solution 2 - Java

It's a lower-bounded wildcard.

JLS 4.5.1 Type Arguments and Wildcards

> Wildcards are useful in situations where only partial knowledge about the type parameter is required. [...] An upper bound is signified by the syntax: > > ? extends B > >where B is the upper bound. [...] it is permissible to declare lower bounds on a wildcard, using the syntax: > > ? super B > >where B is a lower bound.

A List<? super Integer>, for example, includes List<Integer>, List<Number>, and List<Object>.

Wildcards are used to make generics more powerful and flexible; bounds are used to maintain type safety.

See also

As to how this is useful in <T extends Comparable<? super T>>, it's when you have something like Cat extends Animal implements Comparable<Animal>.

Look at the signature of Collections.sort

public static <T extends Comparable<? super T>> void sort(List<T> list)

Therefore, with a List<Cat> listOfCat, you can now Collections.sort(listOfCat).

Had it been declared as follows:

public static <T extends Comparable<T>> void sort(List<T> list)

then you'd have to have Cat implements Comparable<Cat> to use sort. By using the ? super T bounded wildcard, Collections.sort becomes more flexible.

See also
  • Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
    • Also, PECS principle: "producer extends consumer super"

Solution 3 - Java

It means that T must implement Comparable<T itself or one of T's superclasses> The sense is that because SortedList is sorted, it must know how to compare two classes of its generics T parameter. That's why T must implement Comparable<T itself or one of T's superclasses>

Solution 4 - Java

It means that the type T must implement Comparable of T or one of its super classes.

For example, if A extends B, if you want to use SortedList<A>, A must implement Comparable<A> or Comparable<B>, or in fact just Comparable.

This allows the list of As to be constructed with any valid comparator.

Solution 5 - Java

Consider the following example:

  1. Using a type parameter defined in the class declaration

    public class ArrayList extends AbstractList ... {
    public boolean add(E o) // You can use the "E" here ONLY because it's already been defined as part of the class

  2. Using a type parameter that was NOT defined in the class declaration

     public <T extends Animal> void takeThing(ArrayList<T> list)
                                                 // Here we can use <T> because we declared "T" earlier in the method declaration                  
     
    

    If the class itself doesn't use a type parameter, you can still specify one for a method, by declaring it in a really unusual (but available) space - before the return type. This method says that T can be "any type of Animal".

NOTE:

public <T extends Animal> void takeThing(ArrayList<T> list)             

is NOT same as              
      
public void takeThing(ArrayList<Animal> list)

Both are legal, but they are different. The first one indicates that you can pass in a ArrayList object instantiated as Animal or any Animal subtype like ArrayList, ArrayList or ArrayList. But, you can only pass ArrayList in the second, and NOT any of the subtypes.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionShrimpCrackersView Question on Stackoverflow
Solution 1 - JavaYishaiView Answer on Stackoverflow
Solution 2 - JavapolygenelubricantsView Answer on Stackoverflow
Solution 3 - JavaPetar MinchevView Answer on Stackoverflow
Solution 4 - JavaJohn SmithView Answer on Stackoverflow
Solution 5 - JavaEpitaphView Answer on Stackoverflow