Unbounded Wildcards - [OOP & Java #10]
Tags: computerscience, java, codenewbie
Published: 2020-10-31 14:01:07

I discussed generics and bounded wildcards in the below article.
{% link https://dev.to/tlylt/bounded-generic-types-wildcards-oop-java-6-1mcc %}

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:
```java
// 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:
```java
// 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>());

// this does not work
test2(new ArrayList<Integer>());

// this works
test2(new ArrayList<Object>());
```
- The method `test` can take in a list of any type
- The method `test2` can only take in a list of type `Object`

`List<?>` might be useful when:
- Only functionalities provided in the `Object` class are being used.
- Operations do not depend on the type parameter, such as static methods of `List` : `List.size` or `List.clear`.

---
### Question 2
>What is the difference between `List<?>` and `List<? extends Object>` ?

I was not aware of the above until I researched unbounded wildcards. 
- List<?> is unbounded, means a list of any type
- List<? extends Object> is bounded, means a list of any type that extends from Object. Given that all classes in Java are subclasses of the Object class, any type can be used here as well.

Looking at the previous example, they both seem to serve the same purpose:
```java
void test(ArrayList<?> myList) {}

void test2(ArrayList<? extends Object> myList) {}

// this works
test(new ArrayList<Integer>());

// this works
test(new ArrayList<Object>());

// this works
test2(new ArrayList<Integer>());

// this works
test2(new ArrayList<Object>());
```
The one difference mentioned in the article [Java Generics](https://www.baeldung.com/java-generics-vs-extends-object) is the following:

> Reifiable types are those whose type is not erased at compile time. In other words, a non-reifiable type's runtime representation will have less information than its compile-time counterpart, because some of it'll get erased. The only exception to this rule is unbounded wildcard types. 

Generic types are erased during runtime. This means `List<Integer>` becomes the raw type `List` after compile time. However, `List<?>` will remain as `List<?>` after compile time. If we have information about the generic type, we can apply `instanceof` on it.
So,
- `List<? extends Object>` is not reifiable, during runtime it becomes `List`.
- `List<?>` is reifiable, during runtime it becomes `List<?>`.

```java
// this compiles
// allowed to use instanceof on unbounded wildcards
List aList = new ArrayList<Integer>();
aList instanceof List<?>;

// this does not compile
// not allowed to use instanceof on bounded wildcards
aList instanceof List<? extends Object>;
```
I don't think this difference is significant, but it does not hurt to know more:)

---
### Question 3
> Can return types be `?` or `List<?>`?

According to Oracle's [Java tutorial](https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html),
> Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards.

So, it is possible but not recommended. Actually, there is a problem with the return type being `?` or `List<?>`. 
- For `?`

There will be compile time error if we declare our return type to be `?`
```java
test.java:27: error: illegal start of type
    public ? test() {
error: invalid method declaration; return type required
    public ? test() {
```
- For `List<?>`

Supposed we do have such a method that return such an object, what target type can we use to receive it?
```java
// method declaration
public List<?> test() { return new ArrayList<Integer>();}

// this does not work
// error: incompatible types: java.util.List<capture#1 of ?> 
// cannot be converted to java.util.List<java.lang.Integer>
List<Integer> ls  = test(); 

// this works but may be of little use
List<?> ls = test(); // does compile
```
Even if we know that the returned object is actually `List<Integer>`, we cannot assign `List<?>` to any concrete types such as `List<Integer>`. Therefore we also cannot invoke any `Integer` related methods on the items within the list. We gain the benefits of using generic wildcards as a black box, but we lose the ability to manipulate it afterward.

---
### Reference
- [ArrayList Java API]
(https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ArrayList.html)
- [Stackoverflow - ? vs object] (https://stackoverflow.com/questions/35272848/java-generics-unbound-wildcards-vs-object)
- [Unbounded Wildcards](https://docs.oracle.com/javase/tutorial/java/generics/unboundedWildcards.html)
- [Java Generics](https://www.baeldung.com/java-generics-vs-extends-object)