Difference between an unbound wildcard and a raw type
Asked Answered
B

5

39

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>?

Beka answered 9/1, 2013 at 16:48 Comment(2)
Note that the term "raw type" refers to an unparameterized reference to a generic type, e.g. List vs. List<?>. Slightly different concepts.Rambunctious
Just to point out that List<Object> is not a raw type, its generic type is Object. A raw type would be List.Breechloader
C
50

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);
Copywriter answered 9/1, 2013 at 16:50 Comment(5)
got it so far but how raw type is different for unbound and why do we need unboud wildcard? can you please explain it with some good example.Beka
@Beka the main difference IMO is that use of unbound wildcard (e.g. in a method signature) signals a promise that the method in question is aware of generics and will honor the generic type of that object. With raw types all bets are off - you can add a number to a list of strings, as illustrated here - and mixing generic and raw code can lead to the risk of ClassCastExceptions.Rambunctious
@Beka I illustrated the difference between unbouded (2nd example) and raw types (2rd example). What is not clear about them?Copywriter
@Copywriter Nice answer. This comes a bit late, but I have this kind of structure, List<ScheduledFuture<?>>. In a wrapped executor, just to be able to better manage the tasks. So when I create a new scheduled task, it have to be returned. Otherwise the service cannot cancel the task. I cannot see any point in returning a generic ScheduledFuture<?> newScheduledTask() {} instead of just a raw, ScheduledFuture newScheduledTask() {}. What would you recommend in that case?Langue
@Langue Using <?> forces the compiler to verify generics safety - if you use a raw type, the compiler won't check anything and it can create some insidious bugs (can't find an example right now though). Since it makes little difference, I would stick to using <?>.Copywriter
A
6

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<?>

Aspersorium answered 9/1, 2013 at 17:27 Comment(0)
R
6

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;
Regorge answered 12/6, 2018 at 9:44 Comment(0)
C
5

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.

Corner answered 10/2, 2014 at 20:54 Comment(0)
D
4

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
Debate answered 28/10, 2015 at 21:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.