3

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)

thSoft
  • 21,755
  • 5
  • 88
  • 103

1 Answers1

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

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • There is a case to be made for `public static Iterable take(Iterable source, int count)` which lets the compiler infer the type arguments for `Iterable nums = take(ints, 3);`. – Ben Schulz Jul 10 '12 at 15:36
  • Thanks! Regarding comparison: isn't specifying a generic type more type-safe as described here? http://rickyclarkson.blogspot.de/2006/12/making-equalsobject-type-safe.html – thSoft Jul 12 '12 at 12:33
  • No, not really; that article is based on the (false) premise that objects of different types should always be unequal. It is right and proper that e.g. a `LinkedList` can equal an `ArrayList`, and that `Object.equals` takes an `Object` argument. – Louis Wasserman Jul 12 '12 at 13:00