13.5. Using Wildcards as Type Parameter Arguments
You express a particular type from the set defined by a generic type by supplying a type argument for each of its type parameters. For example, to specify the BinaryTree<> type that stores objects of type String, you specify the type argument as String—so the type is BinaryTree<String>. Instead of supplying a specific type as the type argument for a generic type, you can specify the argument as ?, in which case you have specified the type argument as a wildcard. A wildcard type represents any class or interface type.
You can declare variables of a generic type using a wildcard type argument. For example:
BinaryTree<?> tree = new BinaryTree<Double>();
The tree variable is of type BinaryTree<?> so you can store a reference to any type of BinaryTree<> object in it. In this instance you have stored a reference to an object of type BinaryTree<Double>, but BinaryTree<String> or BinaryTree<?> would be equally acceptable—as long as the type argument is not a primitive type. You can think of the use of a variable of a wildcard type as loosely paralleling the use of a variable of type Object. Because the tree variable type is the result of a wildcard type argument, the actual type of the reference stored is not known, so you cannot use this variable to call methods specific to the object that it references.
You can use a wildcard type argument to specify a method parameter type where there is no dependency in the code on the actual type ...