What's this generics usage in Java? X.<Y>method()
Asked Answered
G

5

18

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 generics chapter:

Collections.<TimeUnit>reverseOrder()

What is this kind of generics usage? I discovered it in some code but never read anything about it. It seems to me it permits to give some help to type inference. I've tried to search about that but it's not so easy to find (and it's not even in the SCJP book/exam!)

So can someone give me a proper explaination of how it works, which are all the usecases etc?

Thanks


Edit Thanks for the answers but i expected more details :) so if someone want to add some extra informations:

What about more complex cases like

  • Using a type declared in class , can i do something like Collections.<T>reverseOrder() for exemple?
  • Using extends, super?
  • Using ?
  • Giving the compiler only partial help (ie O.manyTypesMethod<?,MyHelpTypeNotInfered,?,?,?,?,?>() )
Gman answered 8/6, 2012 at 8:44 Comment(0)
R
18

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.

Retouch answered 8/6, 2012 at 8:46 Comment(0)
H
3

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.

Heterogeneous answered 8/6, 2012 at 8:49 Comment(0)
Y
1

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.

Yetac answered 8/6, 2012 at 9:4 Comment(0)
T
1

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).

Thermopylae answered 8/6, 2012 at 13:42 Comment(2)
Thanks. So you mean type inference doesn't work for method parameters??? Is it always the case?Gman
@SebastienLorber I'm not sure. Also, i think Java 7 added some type inference features, although the first example still doesn't compile. One thing that was added was type inference for generic constructor calls, but it works in the same way as generic methods it seems, i.e. assigning to a variable uses type inference but using the expression as a parameter directly doesn't :SThermopylae
S
0

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.

Selfexistent answered 8/6, 2012 at 8:50 Comment(1)
Sorry but the type in this case has nothing to do with the kind of ordering: i can give the type i want, under the hood it will always be the same runtime object doing the exact same thing. The specified type just helps the compilerGman

© 2022 - 2024 — McMap. All rights reserved.