We’ve seen that generic code can take type arguments to help generalize our code. We can make our code even more general when we don’t need the more strict type checking of using type parameters by using wildcards. A wildcard, denoted by the ? symbol, represents an unknown type when used with generic methods. Let’s look at an example:

public class Util { public static void printBag(Bag<?> bag ) { System.out.println(bag.toString()); } } Bag<String> myBag1 = new Bag("Hello"); Bag<Integer> myBag2 = new Bag(23); Util.printBag(myBag1); // Hello Util.printBag(myBag2); // 23

In the example above we defined a static generic method that works on Bag types. We specify that the Bag, which is a generic class, can be of any type by using the wildcard, Bag<?>. We also created two Bag references of different types, String and Integer, and used them as arguments to printBag().

You may be thinking how this is different than using a type parameter because we could write the above method as:

public static <T> void printBag(Bag<T> bag ) { System.out.println(bag.toString()); }

In the example above, we’ve defined the parameter as Bag<T> as opposed to Bag<?> and in this implementation makes no difference but you may notice that the wildcard version is simpler. It’s simpler in not needing the extra <T> before the return type and easier to make sense of when reading the signature.

In general, we should use type parameters, when we have a relationship between the type of arguments and the return type, for example:

public static <T> Bag<T> getBag(Bag<T> bag ) { return bag; }

In the example above we created a method that accepts a Bag of some type T and returns a Bag of the same type T. This use of type parameters maintains strong type checking through our code.

We can also create upper bounds and lower bounds (we’ll see this later) when using wildcards. For example:

public static void printBag(Bag<? extends Number> bag ) { System.out.println(bag.toString()); }

In the example above, printBag() accepts any Bag that is a Number and will error out when passing a type of Bag that does not fall into that parent-child hierarchy, for example, a String Bag.

Let’s practice using wildcards in our generic code.


Take a look at the code in the editor to see how wildcards can be used with our Container class.

Take this course for free

Mini Info Outline Icon
By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.

Or sign up using:

Already have an account?