Java Wildcard Tutorial

In this section, we will learn what the wildcard is and how it works in Java.

What is Java Wildcard?

Sometimes we have a variable of type generic, but we don’t have an object to assign to it.

In a situation like this, when we don’t know what the final object to a variable (parameters as well) will be, we can set the question mark `?` as the `type parameter` in the angle brackets.

The question mark `?` is called wildcard. This means the `type parameter` of the target variable is unknown.

Java generic wildcard example:

import java.util.ArrayList;

public class Simple {

    public static void printList(ArrayList<?> arrayList){
        System.out.println(arrayList);
    }
    public static void main(String[] args) {
        ArrayList<String>arrayList = new ArrayList<>();
        arrayList.add("One");
        arrayList.add("Two");
        arrayList.add("Three");
        printList(arrayList);
    }
}

Output:

[One, Two, Three]

Note: the `ArrayList` is a generic type and it can be used to store elements into an object of this type. (You’ll learn more about this class in ArrayList section).

Here the `check` method has one parameter, and that is of type `ArrayList<?>`. The type of the parameter denotes that the parameter accepts any object of type `ArrayList` with any `type parameter` set for it.

Types of wildcard in Java:

There are three types of wildcard in Java:

  • Unbound wildcard
  • Upper bound wildcard (extends wildcard)
  • Lower bound wildcard (super wildcard)

Java Unbound Wildcard

Basically, when using the `?` mark in the angle brackets, the compiler considers the target variable as unbound. This means the variable accepts objects of the generic type with any `type parameter`. If you think about it, this action is somewhat raw and wild! That’s why they call it wildcard. Generally , wildcard means unpredictable, with no defined role!

For example, here the type parameter of the object that we sent to the `check` method was `String` but we could change the type and use others and send them to the `check` method without any problem.

Example: Creating unbound wildcard

import java.util.ArrayList;

public class Simple {

    public static void printList(ArrayList<?> arrayList){
        System.out.println(arrayList);
    }
    public static void main(String[] args) {
        ArrayList<Integer>arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        printList(arrayList);
    }
}

Output:

[1, 2, 3]

Java Upper bound wildcard (extends wildcard)

When we use wildcards, we’re basically allowing any object of the target generic class with any `type parameter` to be assigned. But sometimes we have boundaries!

For example, we might only accept those objects that have a type parameter of either `Number` type or a subclass that derives from the `Number` class. In such a case, we can use `upper bound wildcard`.

Here’s how it works:

<? extends class/interface name>

Note: after the question `?` mark we use the keyword `extends` and followed by that we put the interface or the class name. This means the target `type parameter` should be either the same as the class/interface we defined here or be a type that derived from the class/interface that is defined here in the angle brackets.

Example: Creating upper bound wildcard

public class Simple {

    public static void printList(ArrayList<? extends Number> arrayList){
        System.out.println(arrayList);
    }
    public static void main(String[] args) {
        ArrayList<Integer>arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        printList(arrayList);
    }
}

Output:

[1,2,3]

The parameter of the `printList` method is of type `ArrayList<? extends Number>`. This means the parameter only accepts objects that their type parameter is either of type `Number` or a subclass of the `Number` class.

So here, because the `Integer` class is a subclass of the `Number` class, we could pass an object of this type to the `printList` method.

Java extends wildcard example:

import java.util.ArrayList;

public class Simple {

    public static void printList(ArrayList<? extends Number> arrayList){
        System.out.println(arrayList);
    }
    public static void main(String[] args) {
        ArrayList<String>arrayList = new ArrayList<>();
        arrayList.add("check");
        arrayList.add("two");
        arrayList.add("Apple");
        printList(arrayList);
    }
}

Output:

Error:(15, 19) java: incompatible types: java.util.ArrayList<java.lang.String> cannot be converted to java.util.ArrayList<? extends java.lang.Number>

Here we got an error, and that’s because we tried to pass an object with a type parameter of `String` which is not a subclass of the `Number` class.

Java Lower bound Wildcard (super wildcard)

Lower bound wildcard is another way of putting boundary on the range of objects that can be passed to a parameter of type wildcard (unknown).

Let’s see the structure:

<? super class/Interface name>

Here after the question `?` mark we used the keyword `super` and followed by that is the name of the class/interface.

When using a lower bound wildcard, that means the target object should have a type parameter that either is the class/ interface that we defined or be a parent of this type in the angle brackets.

Example: Creating lower bound wildcard

import java.util.ArrayList;

public class Simple {

    public static void printList(ArrayList<? super Integer> arrayList){
        System.out.println(arrayList);
    }
    public static void main(String[] args) {
        ArrayList<Integer>arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        printList(arrayList);
    }
}

Output:

[1,2,3]
Facebook
Twitter
Pinterest
LinkedIn

Top Technologies