Search code examples
javagenericsbounded-wildcardgeneric-method

What's the correct usage of generic wildcards when defining functional Java APIs?


I'm writing functional-style static helper methods acting as operators for a generic abstraction (say Iterable<T>), and I'm a bit confused about when I should use wildcards. What are the correct, most type-safe and simplest method signatures in the following cases, and why?

  • Checking properties:

public static int size(Iterable<?> source)

vs.

public static <T> int size(Iterable<T> source)

  • Transforming:

public static <T> Iterable<T> take(Iterable<T> source, int count)

vs.

public static <T> Iterable<T> take(Iterable<? extends T> source, int count)

  • Combining:

public static boolean elementsEqual(Iterable<?> first, Iterable<?> second)

vs.

public static <T> boolean elementsEqual(Iterable<T> first, Iterable<T> second)

vs.

public static <T> boolean elementsEqual(Iterable<? extends T> first, Iterable<? extends T> second)


Solution

  • public static <T> int size(Iterable<T> source)
    

    is equivalent to

    public static int size(Iterable<?> source)
    

    as long as you don't need to refer to T in the method implementation. I'd err towards the ?, just because it reduces clutter.

    public static <T> Iterable<T> take(Iterable<? extends T> source, int count)
    

    is the more general, and it should work in both cases, so I'd go ahead with that one.

    public static boolean elementsEqual(Iterable<?> first, Iterable<?> second)
    

    is appropriate because Object.equals(Object) doesn't have a narrowed signature.

    (Guava provides many of these methods; you could use that as a reference if you like. Disclosure: I contribute to Guava.)