I discussed generics and bounded wildcards in the below article.
While I covered most of the basics about generics and wildcards, there are still areas requiring further attention and discussion. In this article, I would like to pen down some subtleties with regard to unbounded wildcards.
Motivation
Some common questions around this topic are:
1. What is the difference between List<?>
and List<Object>
2. What is the difference between List<?>
and List<? extends Object>
3. Can return types be ? or List<?>
p.s. While I used List<?>
in my examples, I am referring to all possible generic classes, such as custom a generic class named ImmutableList<?>
.
Question 1
What is the difference between `List<?>` and `List<Object>` ?
When we talk about wildcards and generics, our focus is always on type and type safety. The purpose of having these implementations is to allow for polymorphism.
When we have wildcards, we can think of the word “any”. So List<?>
is a list of any possible type. The type is unknown, but we know that any type can replace that ?
and the expression will be a valid one. This is not the case with List<Object>
. Due to invariance, the subtyping relationship like the following does not hold for generics:
// This works
Number[] myArr = new Integer[]();// This does not work
List<Number> myDemo = new List<Integer>();
If they appear in a parameter declaration, there are some obvious differences:
// example method declaration
void test(ArrayList<?> myList) {}// example method declaration
void test2(ArrayList<Object> myList) {}// this works
test(new ArrayList<Integer>());// this works
test(new ArrayList<Object>());