6

What does this mean?

HashBiMap<Character, Integer> charOcc = HashBiMap.<Character, Integer> create();
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
nanda
  • 24,458
  • 13
  • 71
  • 90
  • 4
    Actually, is that even necessary? I think the compiler should be able to infer the generic type parameters from the left-hand side. – Michael Myers Jan 12 '10 at 15:57
  • 1
    Should but won't. In Java you have to declare obsolutely everything. – mcv Jan 12 '10 at 16:01
  • 5
    @mcv - you are mistaken - the compiler can infer the types from the left-hand side. – McDowell Jan 12 '10 at 16:03
  • 1
    Google Collections makes use of this fact in their utility classes, if I remember correctly. `Map myMap = Maps.newHashMap();` – Michael Myers Jan 12 '10 at 16:07
  • 1
    HashBiMap is in fact from Google Collections and that method is there specifically so you don't have to write the type parameters on the right side when creating an instance of it. – ColinD Jan 12 '10 at 16:22
  • I often see this when using Arrays.asList() as this is the most common method I use which has a generic static method. See the Arrays class for the method signature – RNJ Dec 05 '12 at 12:14

6 Answers6

8

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 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 Jan 12 '10 at 15:56
  • 2
    @Bozho: But the position with respect to the dot is odd, and I don't like it in the definition either :) – Jon Skeet Jan 12 '10 at 15:58
  • @Downvoter: Did you downvote because I expressed a dislike of the Java syntax, or because you think I've said something inaccurate? – Jon Skeet Jan 12 '10 at 18:58
8

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: Generic method in Java without generic argument

Community
  • 1
  • 1
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
4

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

public static <Character, Integer> HashBiMap<Character, Integer> create() {..}
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
3

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);
Dónal
  • 185,044
  • 174
  • 569
  • 824
1

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
  • 3,765
  • 1
  • 29
  • 33
0

If you wish to avoid the cumbersome syntax of providing the formal parameters, you can use a cast to type hint.

Using your example,

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

This will be accepted by the compiler and avoids having to use

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