5

In the Java tutorials, it is sometimes written things like this :

Set<?> unknownSet = new HashSet<String>();

While I understand the benefits of using type parameters and wildcards in class definitions and methods, I am wondering the following:

  • What are the benefits of giving a variable a type that comprises a wildcard ?
  • In real life, do people do that, and when ?
Vic Seedoubleyew
  • 9,888
  • 6
  • 55
  • 76
  • Closely related: http://stackoverflow.com/questions/18176594/when-to-use-generic-methods-and-when-to-use-wild-card and http://stackoverflow.com/questions/2922811/whats-the-purpose-behind-wildcards-and-how-are-they-different-from-generics – Tunaki Aug 10 '16 at 14:59
  • Wildcards are only really useful in method parameter declarations, as they increase the range of acceptable parameter types. Wildcards in return types make life difficult (or, rather, messy) for users of your class; wildcards in your local variables just aren't necessary (except to accept the results of wildcard-returning methods). To quote *Effective Java 2nd Ed*, " If the user of a class has to think about wildcard types, there is probably something wrong with the class’s API." – Andy Turner Aug 10 '16 at 15:13

3 Answers3

3

Wildcards are only really useful in method parameter declarations, as they increase the range of acceptable parameter types, for example:

void original(List<Number> list) { /* ... */ }
void withUpperWildcard(List<? extends Number> list) { /* ... */ }
void withLowerWildcard(List<? super Number> list) { /* ... */ }

original(new ArrayList<Number>());       // OK.
original(new ArrayList<Integer>());      // Compiler-error.
original(new ArrayList<Object>());      // Compiler-error.

withUpperWildcard(new ArrayList<Number>());  // OK.
withUpperWildcard(new ArrayList<Integer>());  // OK.

withLowerWildcard(new ArrayList<Number>());  // OK.
withLowerWildcard(new ArrayList<Object>());  // OK.

Wildcards in return types make life difficult (or, rather, messy) for users of your class, since you have to either propagate them, or do explicit work to make them go away, for example:

List<? extends Number> method() { /* ... */ }

// Compiler error.
List<Number> list1 = method();
// OK, but yuk!
List<? extends Number> list2 = method();         
// OK, but the list gets copied.
List<Number> list3 = new ArrayList<Number>(method());  

Wildcards in your local variables just aren't necessary (except to accept the results of wildcard-returning methods).

To quote Effective Java 2nd Ed:

If the user of a class has to think about wildcard types, there is probably something wrong with the class’s API.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
2

This indeed doesn't make much sense. Unless the only thing you want is to read it:

Set<?> unknownSet = new HashSet<String>();
System.out.println(unknownSet); // prints empty set: []
unknownSet.add("salala"); // compile error

On the other hand, the Diamond Operator is cleaner and a bit more useful:

Set<String> unknownSet = new HashSet<>();
unknownSet.add("salala"); // okay now
System.out.println(unknownSet); // prints single set: [salala]

Finally, with a generic object type you can create mixed sets. But those are difficult to debug:

Set<Object> unknownSet = new HashSet<>();
unknownSet.add("salala"); // adding a String
unknownSet.add(42); // adding an Integer
System.out.println(unknownSet); // prints set, sg like this: [42, salala]
Tamas Rev
  • 7,008
  • 5
  • 32
  • 49
1

This is the case of unbounded wildcard.

It was mentioned there its advantages :

If you are writing a method that can be implemented using functionality provided in the Object class. When the code is using methods in the generic class that don't depend on the type parameter. For example, List.size or List.clear. In fact, Class is so often used because most of the methods in Class do not depend on T.

But when declaring a variable, I agree it is NOT anything more useful because your variable was already bounded by RHS side and infact you cannot add String elements to it as pointed out in the other answer. The unbounded wildcard is more useful in methods like the printList used in the example mentioned in the above link.

SomeDude
  • 13,876
  • 5
  • 21
  • 44