6

I wish to understand this concept:

  1. T object - generic, will be erased into actual type.
  2. ? object - will be erased into what?
  3. Object object;

What are the differences between T, ? and Object?

I can easily understand #1, but what about:

Object var;
? var;

What is the difference between the two? I have read that I can't use ? explicitly, like T or any other variable, and that ? is related to objects, not types.
But what is the practical reason? Why can't I just write a List of objects (List<Object>) instead of a List of wildcards (List<?>)? As I don't know the types of objects on both cases.
In addition, I would like to know what is the erasure for ? ?

Idos
  • 15,053
  • 14
  • 60
  • 75
avalon
  • 2,231
  • 3
  • 24
  • 49
  • I'd start with http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html . Specifically look up "Wildcard Capture" – kervin Jan 25 '16 at 13:22
  • And some more good links in http://stackoverflow.com/questions/12043874/java-generics-wildcard-capture-misunderstanding – kervin Jan 25 '16 at 13:27
  • http://bayou.io/draft/Capturing_Wildcards.html – ZhongYu Jan 25 '16 at 18:49

1 Answers1

11

I will list the main differences between T and ?:

  • Basic: T is a type parameter and ? is a wildcard.

  • Meaning: T is used as a type parameter when defining a generic class. T will be replaced by a concrete type when you instantiate the generic class. On the other hand, we use ? when we want to refer to an unknown type argument.

  • Place of definition: You need to declare T on the top of the class, or method if you define a generic method. You can use ? everywhere.
  • Mapping: Every use of T is mapped to the same type (in the same class). Every use of ? can be mapped to a different type.
  • Object instantiation: You can create objects with the generic parameter T like new ArrayList<T>(). You cannot instantiate objects but only pointers with ?.
  • Collections updating: You can add objects to a collection of type T. You cannot add object to a collection of type ? (since you don't know its type).

  • Type erasures: With generics, type erasure applies to the use of generics. when generics are used, they are converted into compile-time checks and execution-time casts. So if you have this code for example: List<String> myList = new ArrayList<String>(); and then you wish to add to your list so you do myList.add("Hello World"); and then you want to get the item you just added by performing String myString = myList.get(0); then the compiler will compile your code to List myList = new ArrayList(); and String myString = (String) myList.get(0); (the add stays the same for obvious reasons).
    So basically, at execution time there is no way of finding out that T is essentially String for the list object (that information is gone).

    Now for wildcards the story is different. A wildcard (?) is replaced by an Object (since it's unbounded). This is not very useful. At build-time the compiler will check you are only calling Object's behaviours. If you have something like ? extends Foo, then the ? is replaced with its bound Foo (at build-time the compiler will check you are only passing Foo or any of its subtypes (types that inherit from Foo) as an argument).

For differences between ? and Object & T and Object you may read here and here respectively.

Community
  • 1
  • 1
Idos
  • 15,053
  • 14
  • 60
  • 75