Class<? super T> getSuperclass()
The getSuperclass() in Class class return a Class whose type is<? super T>, which mean that the type parameter of Class of the Super could be T or any of its Superclasses, now how come a SuperClass's Class type parameter be the same type as the subclass?
for example
Class<Manage>.class.getSuperclass()
doesn't return
Class<Manager>
at all ..like never
Does this make sense? or i am missing something here?
The bound is just a overly-broad because it's as close as you can express using Java's generics.
What you really want is <the immediate superclass of T>; but there's no way to write that in Java's generics. There's also no way to write <? super T excluding T>. <? super T> is pretty much as specific as you can get given the way Java's generics work.
For what it's worth you can guarantee that the class you get back will be the superclass in question -- no matter what its type bound is.
There's no way with Java generics to specify "some superclass but not the class itself." So the provided bound is the best one you can possibly specify.
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.
I understand the <? extends T> in Java is crudely equivalent to the existential qualifier (∃) but is <? super T> related to the universal qualifier (∀)?
Feel free to correct me if I'm wrong about ∃.
It's early and I'm confused, so may well be talking nonsense. I could buy that both are existential, as direction need not negate the logic for a "for some" relationship..?
Partially prompted by the fact that List[_] in Scala is described as existential and that's roughly the same as List<?> in Java.
Wildcard types (both ? extends T and ? super T) form a subset of existential types. Both of these you can read like "there exists some type which (extends|is supertype of) T". The key idea is that you don't know exact type.
Universal types are just type parameters. For example, here:
class List<T> { ... }
T is arbitrary, like it has an implicit universal qualifier.
Its not really related to predicate logic, its related to the type hierachy. I can understand why you might read out loud <? extends T> as "For all T's" but its extended to "For all objects that have a super class of T" rather than "For all T in X" as in predicate logic.
Similarly <? super X> should be read as "For objects that are of a type that is a super class on X"
The main difference between <? super T> and <? extends T> is that the first declaration says that some type is an ancestor of T and the second says that some type is a subclass of T. I don't see any correlation with existential qualifier or universal qualifier here. As someone noticed in the comments, the more likely similarity (if you really must have one) is type floor and ceiling. Nevertheless, it's really an abstract analogy.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is a difference between <? super E> and <? extends E>?
Some Java programmers on a team I'm on are writing functions that return objects of type List<? extends T> to make read-only lists and return objects of type List<? super T> to make write-only lists.
In Java, what makes List<? extends T> read-only and List<? super T> write-only?
please read up on "producer extends, consumer super" (PECS) - I may need to do the same :)
Read only:
In case you would like to ensure that a method takes as a parameter a collection of items ( using generics) - when you use List<? extends T> - the list can contain any subtype of T but cannot add to the collection since it does not know at runtime the specific type of T that the List contains.
Write only:
For List<? super T>, the list can contain T regardless of the actual parameterized type (using super will allow that to happen).
Hope it helps.
You can get a T from a List<? extends T>, but the only thing you can put into it is a null literal. You can put a T into a List<? super T>, but the only thing you can get from it is an Object (which is then unsafe to cast down to T).
So, the restrictions make these pretty good, though imperfect, reminders of the intention. With a List<? extends T>, you can't put most things into it -- so it's kinda read-only. And with a List<? super T>, you can't get things out of it very usefully -- so it's kinda write-only.
Note that neither one of these is actually read- or write-only. I noted some of the ways you can get things into or out of them above, and with the "read-only" construct, you can still call remove functions, either on the object itself or on its iterator.
The definition List<? extends T> means "a List<X> implementation, where X must be T or a subclass/implementation thereof. In other words, your only guarantee is that objects already stored in the list will fit in a variable of type T. However, since the list may have been declared for a class extending or implementing T, you have no guarantee that objects of type T itself will fit into the list.
Simple example: List<String> is a List<? extends T> if T is Object. You can safely draw Object-type objects from it, but you can obviously not put other Object-type objects in it, unless they are definitely strings.
What are the differences between the following three signatures?
static <T> void foo(List<T>, Comparator<? super T>);
static <T> void bar(List<? extends T>, Comparator<T> );
static <T> void baz(List<? extends T>, Comparator<? super T>);
I know what extends and super mean in Generics. My question is whether there is a difference between foo, bar and baz. Should I make one of the parameters invariant and the other one variant in the appropriate direction, or should I make both of them variant? Does it make a difference?
PECS - Producer extends, consumer super.
To explain this "rule":
extends means the genericized object produces elements of the type. When it's a collection, it means you can only take elements from the collection, but not put them in. The comparator
super means the object consumes objects of the selected type. So you can add to the collection, but not read from it.
the lack of extends and super means you can do both for the exact type specified.
Regarding the Comparator, I don't think it makes any difference. Normally, it would be <? super T> because you the comparator consumes objects, but in all three cases you can safely invoke Collections.sort(list, comparator); (the signature of which is <? super T>)
The only difference is whether T represents the type parameter of the List, the Comparator, or something in between.
As far as the caller is concerned, the three method signatures are equivalent, i.e. whenever one of them can be used, the others can be used as well.
For the method implementation foo is probably most convenient, as it allows modifying the list without needing an additional capture conversion, which would require delegating to a helper method.
I believe that ? extends T means that the List may be generic of any type that is derived from T, whereas List<T> can only be a List of T and not any of its derived classes.
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.