The two examples are telling you different things, so they are not redundant, they give different information and restricts the type in a different way.
public static <T extends Comparable> T findMax(List<T> list)
In this example, you are telling your T
variable can be of any type that implements or extends Comparable
(if it is a class or an interface)
public static <T extends Comparable<? super T>> T findMax(List<? extends T> list)
In this example, you are telling that the T
type should extends comparable and also telling that the type must be a super class of T
(inside comparable) but it can be a sub-type of T
in the list.