I\'ve read the whole SCJP6 book Sierra and Bates book, scored 88% the exam.
But still, i never heard of how this kind of code works as it\'s not explained in the generic
In this case it is a way of telling the reverseOrder method what kind of ordering should be imposed on the object, based on what type you specify. The comparator needs to get specific information about how to order things.
Just a small addition to the other responses.
When getting the according compiler error:
While the "traditional" casting approach
(Comparator<TimeUnit>) Collections.reverseOrder()
looks similar to the generics approach
Collections.<TimeUnit>reverseOrder()
the casting approach is of course not type-safe (possible runtime exception), while the generics approach would create a compilation error, if there is an issue. Thus the generics approach is preferred, of course.
It is explicit type specification of a generic method. You can always do it, but in most cases it's not needed. However, it is required in some cases if the compiler is unable to infer generic type on its own.
See an example towards the end of the tutorial page.
Update: only the first of your examples is valid. The explicit type argument must be, well, explicit, so no wildcards, extends
or super
is allowed there. Moreover, either you specify each type argument explicitly or none of them; i.e. the number of explicit type arguments must match the number of type parameters of the called method. A type parameter such as T
is allowed if it is well defined in the current scope, e.g. as a type parameter of the enclosing class.
You are 100% correct, it is to help with type inference. Most of the time you don't need to do this in Java, as it can infer the type (even from the left hand side of an assignment, which is quite cool). This syntax is covered in the generics tutorial on the Java website.
As the other answers have clarified, it's to help the compiler figure out what generic type you want. It's usually needed when using the Collections
utility methods that return something of a generic type and do not receive parameters.
For example, consider the Collections.empty*
methods, which return an empty collection. If you have a method that expects a Map<String, String>
:
public static void foo(Map<String, String> map) { }
You cannot directly pass Collections.emptyMap()
to it. The compiler will complain even if it knows that it expects a Map<String, String>
:
// This won't compile.
foo(Collections.emptyMap());
You have to explicitly declare the type you want in the call, which i think looks quite ugly:
foo(Collections.<String, String>emptyMap());
Or you can omit that type declaration in the method call if you assign the emptyMap return value to a variable before passing it to the function, which i think is quite ridiculous, because it seems unnecessary and it shows that the compiler is really inconsistent: it sometimes does type inference on generic methods with no parameters, but sometimes it doesn't:
Map<String, String> map = Collections.emptyMap();
foo(map);
It may not seem like a very important thing, but when the generic types start getting more complex (e.g. Map<String, List<SomeOtherGenericType<Blah>>>
) one kind of starts wishing that Java would have more intelligent type inference (but, as it doesn't, one will probably start writing new classes where it's not needed, just to avoid all those ugly <>
=D).