Question

I was reading about generics and I did not understand the need for unbound wildcards and how it differs from raw type. I read this question but still did not get it clearly. In the Java tutorial page for unbound wildcard I got below two points and I did not understood first point:

  • 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<T> do not depend on T.

Can someone please explain the difference between unbound wildcard and raw type in layman language.

How does List<?> differ from List<Object>?

Was it helpful?

Solution

How List<?> differs from List<Object>

The main difference is that the first line compiles but the second does not:

List<?> list = new ArrayList<String> ();
List<Object> list = new ArrayList<String> ();

However, because you don't know what the generic type of List<?> is, you can't use its parameterized methods:

List<?> list = new ArrayList<String> ();
list.add("aString"); //does not compile - we don't know it is a List<String>
list.clear(); //this is fine, does not depend on the generic parameter type

As for the difference with raw types (no generics), the code below compiles and runs fine:

List list = new ArrayList<String> ();
list.add("aString");
list.add(10);

OTHER TIPS

How List<?> differs from List<Object>?

    List<Object> l1 = new ArrayList();
    List<?> l2 = new ArrayList();
    l1.add("Object");
    //l2.add("Object");   incorrect
    l2.add(null);

You can only add null-value to the List<?>

Can someone please explain the difference between unbound wildcard and raw type in layman language.

Unbound wildcard type can maintain collection’s type invariant, and raw type cannot. As Joshua Bloch says in his Effective Java,

You can put any element into a collection with a raw type, easily corrupting the collection’s type invariant(as demonstrated by the unsafeAdd method on page 112); you can’t put any element (other than null) into a Collection<?>.

So, as long as you assign a list of parameterized type to a list of unbound wildcard type, collection’s type invariant will be maintained.

List<String> list1 = new ArrayList();
list1.add("foo");
list1.add("bar");
List<?> list2 = list1;

If you assign a list of raw type whose elements are of different types, unbound wildcard type will not maintain collection’s type invariant, as the list is originally of type variant.

List list1 = new ArrayList();
list1.add(1);
list1.add("foo");
List<?> list2 = list1;

Personally, I found this additional link from the Java tutorial on wildcards helpful.

One of the main differences I see between List<?> and List is that the former can only ever be useful for reading from it's elements (unless you really want to add null), the latter allows (unchecked) adding of arbitrarily typed objects to it with possibly unexpected side-effects.

List is useful in a method signature to call methods that never require the type parameter, i.e., read from the list or rotate it, for instance.

void someMethod(List<?> list) {
  list.clear();  // I will never add anything to the list in here
}

You will never add anything or otherwise modify the list with respect to the type it holds as you cannot add anything to the list except null in methods with this signature and thus you won't ever break type safety. Raw List on the other hand you can do anything to, which as we all know can result in a type safety violation.

void someMethod2(List list) {
 list.add(new WeaselFurBrush());  
}
List list1 = new ArrayList<String>();
someMethod2(list1);// oops
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top