tags:

views:

284

answers:

5
+3  Q: 

Weird Java generic

What does this mean?

HashBiMap<Character, Integer> charOcc = HashBiMap.<Character, Integer> create();
+7  A: 

It's calling a generic static method (create()) using Character and Integer as the type arguments. For instance, if you're looking at the Google Java Collections, the declaration has this signature:

public static <K,V> HashBiMap<K,V> create()

The <K,V> part on its own specifies that those are type parameters for the method.

The equivalent call in C# would be one of:

HashBiMap.Create<Character, Integer>();
HashBiMap<Character, Integer>.Create();

depending on whether you wanted it to be a generic method in a nongeneric type, or a nongeneric method in a generic type.

The positioning of type parameters and type arguments in Java is unintuitive IMO.

Jon Skeet
on the other hand the structure of the calling code follows the structure of the definition - the type perameters first, the name of the method - second.
Bozho
@Bozho: But the position with respect to the dot is odd, and I don't like it in the definition either :)
Jon Skeet
@Downvoter: Did you downvote because I expressed a dislike of the Java syntax, or because you think I've said something inaccurate?
Jon Skeet
+4  A: 

It means that the static create() method has type parameters, like:

public static <Character, Integer> HashBiMap<Character, Integer> create() {..}
Bozho
+7  A: 

create() is a generic method. Since it's static and has no parameters (hence no type inference), the only way you can tell it what the generic parameters are is by that strange-looking .<Character, Integer> syntax.

Edit: This is actually not necessary in this specific case; the compiler can infer the generic types from the left-hand side. But it is sometimes necessary in other cases, such as this question.

Michael Myers
+3  A: 

Presumably it's the right-hand side (RHS) you think is weird

HashBiMap.<Character, Integer> create();

Usually, it's only necessary to use the type parameters on the LHS when calling a generic static method. But sometimes the static method does not infer the type parameters as you intended. In those cases you can also use the type parameters on the RHS in order to coerce the type parameters to whatever you intended. This is known as an explicit type parameter.

Here is an example of when type parameters are not inferred correctly (adapted from the excellent "Effective Java" book):

Example

Given the static method

public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2)

you might think that you could do this:

Set<Integer> integers = ... ;
Set<Double> doubles = ... ;
Set<Number> numbers = union(integers, doubles);

If you try it you’ll get this error message:

Union.java:14: incompatible types
found : Set<Number & Comparable<? extends Number & Comparable<?>>>
required: Set<Number>
    Set<Number> numbers = union(integers, doubles);

If the compiler doesn’t infer the type that you wish it had, you can tell it what type to use with an explicit type parameter. With the addition of this explicit type parameter, the program compiles cleanly:

Set<Number> numbers = Union.<Number>union(integers, doubles);
Don
+1  A: 

HashBiMap probably has a method

public static <K,V> HashBiMap<K,V> create(){...}

Using the syntax

HashBiMap<Character, Integer> charOcc = HashBiMap.<Character, Integer> create();

you are passing Character for K and Integer for V.

Tobias Schulte