This question already has answers here:
Difference between <? super T> and <? extends T> in Java [duplicate]
(14 answers)
Closed 6 years ago.
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 >?
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.
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
Java language guide/Generics/More Fun with wildcards
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"
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>
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.
Consider the following example:
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
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.
Related
Assume I have a class and a method such as this:
class MyClass<T> {
void doStuff(Wrapper<T> wrapper) {
//impl.
}
}
Generic bounds of the parameter "wrapper" can be modified to Wrapper<? extends T> to make the method accept subtypes of T, and Wrapper<? super T> to accept super types. However, is there a way to modify MyClass such that it accepts both sub and super types of T (not any type), and there is only one method name? (there can be overloads)
I could simply go with Wrapper<?> of course, but "accept anything" is not the same as "accept something that's in the class hierarchy for T". I could also make 2 separate methods, one with <? super T> and one with <? extends T>, but then these methods would need different names, since the signature is the same after erasure.
Note: Please consider this a question out of curiosity.
You could try the following
<S extends T> void doStuff(Wrapper<? super S> wrapper)
but would need to double check this satisfies your requirements.
The PECS principle is about what kind of argument you select in a function, depending on how you will use that parameter.
My question is about the fact that, once you chose to use super (because your function possibly is a Consumer), you cannot pass to that function certain generic class instances.
Let's consider the following program:
public class Main{
public static void main(String[] args){
List<?> unbound = new ArrayList<Long>();
List<? extends Long> extendsBound = new ArrayList<Long>();
List<? super Long> superBound = new ArrayList<Long>();
takeExtend(unbound);
takeExtend(extendsBound);
takeExtend(superBound);
takeSuper(unbound);
takeSuper(extendsBound);
takeSuper(superBound);
}
static <T> void takeExtend(List<? extends T> l){}
static <T> void takeSuper(List<? super T> l){}
}
The compiler gives the following error:
error: method takeSuper in class Main cannot be applied to given
types;
takeSuper(unbound);
^ required: List<? super T> found: List<CAP#1> reason: cannot infer type-variable(s) T
(argument mismatch; List<CAP#1> cannot be converted to List<? super T>) where T is a type-variable:
T extends Object declared in method <T>takeSuper(List<? super T>) where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
I was trying to find a sort of symmetry, such as the one we have for the PECS rule, but I didn't find any.
So:
Why is it not possible to pass a <?> or a <? extends T> to a function expecting <? super T>?
Why is it possible to pass a <?> to a function expecting a <? extends T>?
Why is it possible to pass a <? super T> to a function expecting a <? extends T>?
You can think of a generic method (i.e. a method with its own type parameters) as making a set of statements about its type parameters.
For example, the method <T> someMethod(List<T>) is saying:
There exists some type T for which the type parameter of this list equals T.
Easy. All lists fit this criterion, so any list is a valid input to the method.
Everything inside the method can now make use of the knowledge that that statement is true. How is that knowledge useful? Well, if we get an item from the list, we know it matches the list's type parameter. Because we captured the type as T, we can hold a reference to the object and put it back in the list later, all still without knowing what type it really is.
The method declaration <T> someMethod(List<? extends T>) makes a slightly different claim:
There exists some type T for which the type parameter of this list is a subtype of T.
This is also trivially true for all lists. However, you might notice that it makes <T> someMethod(List<? extends T>) a bit useless. You're telling the compiler to capture the fact that items that come out of the list share some common supertype with other items that come out of the list. Unless you have, inside the method, some other consumer that is known to accept <? super T>, there's nothing you can do with that information. It's much less useful than the knowledge that all the items that come from the list are of the same type.
So, why doesn't <T> takeSuper(List<? super T>) work the same way?
The method declaration <T> takeSuper(List<? super T>) can be interpreted as claiming that:
There exists some type T for which the type parameter of this list is a supertype of T.
If we have a List<? super Long> and we pass it to a method that captures <T> takeSuper(List<? super T>) it's easy to see that a reference of type Long would satisfy T. We could pass a Long to the method as a parameter of type T, and then add it to the list from inside the method.
But what about if we have a List<?> and we capture its type using the method <T> takeSuper(List<? super T>)? By declaring the list as a List<?> we're saying that we don't currently know what its type parameter is. In doing that, we're telling the compiler that we have absolutely no way to get a reference of a type that matches the type parameter of the list. In other words, the compiler knows with certainty that no object can satisfy the type parameter T. Remember, for this method, an object is of type T if it is known to be of a type that is a subtype of the type parameter of the list. If we don't know anything about the type parameter of the list, that's impossible.
The same is true for a List<? extends Long>. We know that the items we fetch from the list will be a subtype of Long, but we don't have a lower bound for their type. We can never prove that any type is a subtype of the list's type parameter. So, for the method <T> takeSuper(List<? super T>), there is again provably no way to get a reference of type T.
Interestingly, my compiler (Java 8) doesn't complain about calling the method <T> takeSuper(List<? super T>) with a List<?> as input. I suppose it recognizes that since there's no way to get a reference of type T, there's no harm in just ignoring the useless type parameter.
Why is it not possible to pass a <?> or a <? extends T> to a function expecting <? super T>?
Consider this method:
static <T> void sillyAdd(List<? super T> l, T t){
l.add(t);
}
Now look how we could use it if this were possible:
List<Integer> onlyIntegers = new ArrayList<>();
List<? extends Number> anyNumber = onlyIntegers;
sillyAdd(anyNumber, Float.valueOf(0)); /* Not allowed... */
Integer i = onlyIntegers.get(0);
The last line would throw a ClassCastException because we were allowed to put a Float into a List<Integer>.
Why is it possible to pass a <?> to a function expecting a <? extends T>?
takeExtend(unbound);
There are no bounds on T; it could be any type. While the type parameter of unbound is unknown, it does have some type, and since T can be any type, it's a match.
Methods like this are sometimes used as a helper in some odd corners of generics. Logically, we know that the following should be no problem:
public static void rotate(List<?> l) {
l.add(l.remove(0));
}
But the rules of generics don't imply type-safety here. Instead, we can use a helper like this:
public static void rotate(List<?> l) {
helper(l);
}
private static <T> void helper(List<T> l) {
l.add(l.remove(0));
}
Why is it possible to pass a <? super T> to a function expecting a <? extends T>?
It's not, in a way. Given this example:
static <T> void takeExtend(List<? extends T> l)
List<? super Long> superBound = new ArrayList<Long>();
takeExtend(superBound);
You might think that T is inferred to be Long. That would mean that you passed a List<? super Long> to a method declared like void takeExtend(List<? extends Long> l), which seems wrong.
But T isn't inferred to be Long. If you specify Long explicitly as the type parameter, you'll see that it won't work:
Main.<Long>takeExtend(superBound);
What's actually happening is that T is inferred to be ? super Long, so the generic type of the method is something like void takeExtend(List<? extends ? super Long>). That means that everything in the list is something that extends an unknown super class of Long.
Why is it not possible to pass a <?> or a <? extends S> to a function expecting <? super T>? (Question corrected for clarity: ? extends S).
The compiler wants to infer the T, which is the bottom limit, and it can't. Every class extends Object, but there is no universal inheritance tree bottom class, which the compiler could default to.
Why is it possible to pass a <?> to a function expecting a <? extends T>?
It's about inference. You can pass a <?> because the compiler can make something out of it. Namely, it can make Object out of T. The same happens with the following:
List<?> unbound = new ArrayList<>();
Why is it possible to pass a <? super T> to a function expecting a <? extends T>?
Again, it's about inferring the upper limit now, so the compiler can default to Object. It's not interested in what ? is super to, nor whether it is super to anything at all.
I've been thinking this stuff all night long, with the amazing help of your comments, trying to find an easy-to-remember solution.
This is what I got.
A method accepting a <? extends T>, to get T, must infer the upper limit of that hierarchy. Since in Java every class is extending Object, the compiler can rely on the fact that at least the upper limit is Object. So:
if we pass a <? extends T>, the upper bound is already defined and it
will use that one
if we pass <?>, we don't know anything, but we know
that every class extends Object, so the compiler will infer Object
if we pass <? super T>, we know the lower bound, but since every class
extends Object, the compiler infer Object.
A method accepting a <? super T>, to get T, must infer the lower limit of that hierarchy. In Java by default we can count on an upper bound, but not on a lower bound. So the considerations made in the previous case are not valid anymore. So:
if we pass a <? extends T>, there is no lower bound, because the
hierarchy can be extended as much as we want
if we pass a <?>,
there is no lower bound, because the hierarchy can be extended as
much as we want
if we pass a <? super T>, a lower bound is already
defined, so we can use that one.
Recapping:
a method accepting a <? extends T> can always rely on the fact that
an upper bound exists and that is Object -> we can pass every bound to it
a method accepting a <? super T> can infer a lower bound only if it is explicitly defined in the parameter -> we can only pass a <? super T>
This question already has answers here:
When to use wildcards in Java Generics?
(6 answers)
Closed 8 years ago.
public <? extends Animal> void takeThing(ArrayList<?> list)
public <T extends Animal> void takeThing(ArrayList<T> list)
Why this statement is wrong? I mean why the ? can't be used in the front? But T can. What is the difference?
Possible duplicate "When to use wildcards in Java Generics?"
Here is an answer for this question.But I don't get what this mean.
"if you say void then there is no return type. if you specify then there is a return type. i didn't know that you can specify to have return type or no return type."
Writing <T extends Animal> binds the type name T, so that it can be referred to later in the definition (including in the parameter list).
If you wrote <? extends Animal>, then you did not name the type. Therefore, you cannot refer to it later. You can't refer to it as ? later because that could be ambiguous (what if you had two type parameters?).
Java forbids you from writing public <?> ... because such a declaration is useless (the type parameter is not named so it cannot be used).
public void takeThing(ArrayList<? extends Animal> list)
means "do something with a list of any subclass of Animal".
public <T extends Animal> void takeThing(ArrayList<T> list)
means "do something with a list of some particular subclass (A.K.A. T) of Animal".
If I call list.get() on the first method, all I know about the returned type is that it extends Animal. On the second method, if I had another instance of List<T>, I know that whatever type T is, both lists would accept the same type.
To take it even further, if I say
Animal animal = list.get(0);
I can no longer say
list.add(animal);
even on the very same list, because we don't have a reference to the generic subtype. If however, I declare a List<T> where <T extends Animal>, I can now say
T animal = list.get(0);
list.add(animal);
because we know that list expects elements of type T.
class BinarySearch<T extends Comparable<? super T> >
Why is T extends Comparable <? super T> including T, meaning including Comparable<T> and not just the super class hierarchy? I am confused on the super keyword as I thought super would only include super class items. I am new to java and in the Java book it had the following example:
This is regarding a method in a class that was trying to limit the upper and lower bound of the hierarchy using the Java.awt.Component so the class had extends Container
class CustomComponent<T extends Container>
in the class they have the following method
void describeComponent<CustomComponent<? super JPasswordField> ref)
and then goes on to say
Note that JPasswordField, which is a superclass of JTextField, itself is omitted in the list of permissible objects.
From Lower Bounded Wildcards, a section of the Generics section of The Java Tutorial:
... a lower bounded wildcard restricts the unknown type to be a specific type or a super type of that type.
(bold mine, emphasis theirs)
Thus, the set of classes that match T extends Comparable<T> is a subset of the set of classes that match T extends Comparable<? super T>. The wildcard ? super T itself matches T and any superclasses of T.
In other words, the assumption that "super would only include super class items" is simply incorrect.
Your confusion in the example may also arise from the fact that JTextField is a superclass of JPasswordField; in other words, JPasswordField extends JTextField. The example would match any of the following classes:
javax.swing.JPasswordField
javax.swing.JTextField
javax.swing.JTextComponent
javax.swing.JComponent
java.awt.Container
java.awt.Component
java.lang.Object
The example would make much more sense as the following:
void describeComponent(CustomComponent<? super JTextField> ref) {...}
Note that JPasswordField, which is a subclass of JTextField, itself is
omitted in the list of permissible objects, because it is not a
superclass of JTextField.
I believe the semantic meaning of "<T extends Comparable<? super T> >"
is that either T or a superclass of T must implement Comparable
I have couple of thoughts regarding the following:
public interface MaxStack<T extends Comparable <T>>
1-Why does the class that implements MaxStack should be written like this:
public class MaxStackclass<T extends Comparable <T>> implements MaxStack<T>
and not public class MaxStackclass<T extends Comparable <T>> implements MaxStack<T extends Comparable <T>>?
2- why do the private variables of this class, when I use generics, should be written only with <T> and not with <T extnds Comparable<T>>? For example, private List<T> stack= new ArrayList<T>();
3-What is the difference between <T extends Comparable<T>> and <T extends Comparable>- if I need to compare bewteen elements in my class, both will be O.K, no?
Edit: I think that thee problem with 3 is that maybe it allows to insert of a list that was defined in the second way to have different elements which all extends from comparable and then when I want to compare them, it won't be possible, since we can't compare String to Integer, both extend from Comparable.
In the declaration maxStackclass<T extends Comparable <T>> you have already expressed the bounds on T. So you do not need it again.
Reason same as above. No need to specify bounds on the same type parameter again.
<T extends Comparable<T>> means that T must implement the Comparable interface that can compare two T instances. While <T extends Comparable> means T implements Comparable such that it can compare two Objects in general. The former is more specific.
if I need to compare bewteen elements in my class, both will be O.K,
no?
Well, technically you can achieve the same result using both. But for the declaration <T extends Comparable> it will involve unnecessary casts which you can avoid using the type safe <T extends Comparable<T>>
1) the class has a type parameter T with a bound (extends Comparable <T>), this parameter is passed to the interface (which need the same bound here). When passing a type parameter, you must not repeat its bound - why you should do so?
2) like 1), the type parameter has its bound declared, no repeat neccessary.
To clarify:
The first type parameter occurence (here behind the interface or class name) is its declaration. Any following occurence is a usage. You even never would write a variables type declaration each time you use it, right?
"3-What is the difference between <T extends Comparable<T>> and <T extends Comparable>- if I need to compare bewteen elements in my class, both will be O.K, no?"
No, both will not be okay. Suppose I have a class Foo which implements Comparable<Bar> but classes Foo and Bar have no relation to each other. Then Foo cannot compare to other objects of type Foo. <T extends Comparable<T>> will catch this as a problem. <T extends Comparable> will not.