Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use and point of unbound wildcards generics in Java?

I don't understand what is the use of unbound wildcards generics. Bound wildcards generics with upper boundary <? extends Animal> makes perfect sense, because using polymorphism I can work with that type or collection. But what is the point of having generics that can be of any type? Doesn't it defeat the purpose of generics? Compiler doesn't find any conflict and after type erasure it would be like no generics was used.

like image 473
lisak Avatar asked Oct 06 '11 06:10

lisak


People also ask

What are unbounded wildcards in generics Java?

Unbounded wildcards An unbounded wildcard is the one which enables the usage of all the subtypes of an unknown type i.e. any type (Object) is accepted as typed-parameter. For example, if want to accept an ArrayList of object type as a parameter, you just need to declare an unbounded wildcard.

What is the use of wildcard in generics?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).

Why do we use wildcards in Java generics?

Wildcards in Java are basically the question marks which we use in generic programming, it basically represents the unknown type. We use Java Wildcard widely in situations such as in a type of parameter, local variable, or field and also as a return type.

In which situations would you use unbounded wildcards?

There are two scenarios where an unbounded wildcard is a useful approach: 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.


1 Answers

An unbound type can be useful when your method doesn't really care about the actual type.

A primitive example would be this:

public void printStuff(Iterable<?> stuff) {   for (Object item : stuff) {     System.out.println(item);   } } 

Since PrintStream.println() can handle all reference types (by calling toString()), we don't care what the actual content of that Iterable is.

And the caller can pass in a List<Number> or a Set<String> or a Collection<? extends MySpecificObject<SomeType>>.

Also note that not using generics (which is called using a raw type) at all has a quite different effect: it makes the compiler handle the entire object as if generics don't exist at all. In other words: not just the type parameter of the class is ignored, but also all generic type parameters on methods.

Another important distinctions is that you can't add any (non-null) value to a Collection<?>, but can add all objects to the raw type Collection:

This won't compile, because the type parameter of c is an unknown type (= the wildcard ?), so we can't provide a value that is guaranteed to be assignable to that (except for null, which is assignable to all reference types).

Collection<?> c = new ArrayList<String>(); c.add("foo");    // compilation error 

If you leave the type parameter out (i.e. use a raw type), then you can add anything to the collection:

Collection c = new ArrayList<String>(); c.add("foo"); c.add(new Integer(300)); c.add(new Object()); 

Note that the compiler will warn you not to use a raw type, specifically for this reason: it removes any type checks related to generics.

like image 126
Joachim Sauer Avatar answered Oct 04 '22 20:10

Joachim Sauer