Java 5 – Wildcard arguments in Generics

In this article, we will discuss wildcard arguments in Generics introduced in Java 1.5 version

1. Wildcard arguments:

Question mark (?) is known as wildcard and it represents unknown type. We will discuss three different cases for wildcards,

  1. Unbounded wildcard
  2. Upper-bounded wildcard using extends keyword
  3. Lower-bounded wildcard using super keyword

Note : wildcard can be used strictly with generics method only

1.1 Unbounded wildcard:

  • Here, we took Collection as base-type but it can be anything like ArrayList or HashSet, etc.
  • While using unbounded wildcard in method argument allows to accept any unknown type
  • In the below addition program, ArrayList works well with Integer or String, etc.
  • Syntax:
Collection<?>

UnboundedWildcard.java

package in.bench.resources.generics.wildcard;

import java.util.ArrayList;

public class UnboundedWildcard {

	// generics wildcard method to accept any unknown-type
	public static void addArrayListValues(ArrayList<?> any) {

		// enhanced forEach loop
		for(Object obj : any){
			System.out.print(obj + " ");
		}
		System.out.println("\n");
	}

	// main() method - to begin execution
	public static void main(String[] args) {

		// create ArrayList of Integer
		ArrayList<Integer> intList = new ArrayList<Integer>();

		// add to Integer list
		intList.add(10);
		intList.add(30);
		intList.add(70);
		intList.add(90);

		// invoke generics method with wildcard
		addArrayListValues(intList);

		// create ArrayList of String
		ArrayList<String> strList = new ArrayList<String>();

		// add to String list
		strList.add("East");
		strList.add("West");
		strList.add("North");
		strList.add("South");

		// invoke generics method with wildcard
		addArrayListValues(strList);
	}
}

Output:

10 30 70 90 

East West North South

1.2 Upper bounded wildcard:

  • Here, we took Collection as base-type but it can be anything like ArrayList or HashSet, etc.
  • This ReferenceType can be either class or interface
  • If referenceType is a class, then wildcard (?) can be replaced by either class or one of its sub-classes
  • Similarly, if referenceType is an interface, then Type-parameter T can be replaced by either interface or one of its implementation classes
  • Assume that, if we replace referenceType by Number class as upper bound then it can accepts either Number class or its sub-classes like Integer or Double, etc.
  • In the below addition program, ArrayList works well with Integer or Double, etc.
  • But as soon as String is passed, compile-time error is thrown
  • Compile-time error : The method addArrayListValues(ArrayList<? extends Number>) in the type UpperBoundedWildcard is not applicable for the arguments (ArrayList<String>)
  • as shown screen-capture 2.1 after program UpperBoundedWildcard.java
  • Syntax:
Collection<? extends ReferenceType>

UpperBoundedWildcard.java

package in.bench.resources.generics.wildcard;

import java.util.ArrayList;

public class UpperBoundedWildcard {

	// generics wildcard method to accept any unknown-type
	public static void addArrayListValues(ArrayList<? extends Number> any) {

		// enhanced forEach loop
		for(Object obj : any){
			System.out.print(obj + " ");
		}
		System.out.println("\n");
	}

	// main() method - to begin execution
	public static void main(String[] args) {

		// create ArrayList of Integer
		ArrayList<Integer> intList = new ArrayList<Integer>();

		// add to Integer list
		intList.add(10);
		intList.add(30);
		intList.add(70);
		intList.add(90);

		// invoke generics method with wildcard
		addArrayListValues(intList);

		// create ArrayList of Double
		ArrayList<Double> dblList = new ArrayList<Double>();

		// add to Double list
		dblList.add(10.25);
		dblList.add(20.50);
		dblList.add(30.75);
		dblList.add(40.99);

		// invoke generics method with wildcard
		addArrayListValues(dblList);
	}
}

Output:

10 30 70 90 

10.25 20.5 30.75 40.99

1.2.1 Compile-time error for Upper-bounded wildcard:

1.3. Lower bounded wildcard:

  • Here, we took Collection as base- type but it can be anything like ArrayList or HashSet, etc.
  • This ReferenceType can be either class or interface
  • If referenceType is a class, then wildcard (?) can be replaced by either class or its super-classes
  • Similarly, if referenceType is an interface, then Type-parameter T can be replaced by either interface or super-class of implementation classes of interface
  • Assume that, if we replace referenceType by Integer class as lower bound then it can accepts either Integer class or its super-classes like Number, etc.
  • Anything other than this 2 will results in compile-time error
  • Like passing String to this method results in compile-time error
  • Compile-time error : The method addArrayListValues(ArrayList<? super Integer>) in the type LowerBoundedWildcard is not applicable for the arguments (ArrayList<Double>)
  • as shown screen-capture 3.1 after program LowerBoundedWildcard.java
  • Syntax:
Collection<? super ReferenceType>

LowerBoundedWildcard.java

package in.bench.resources.generics.wildcard;

import java.util.ArrayList;

public class LowerBoundedWildcard {

	// generics wildcard method to accept any unknown-type
	public static void addArrayListValues(ArrayList<? super Integer> any) {

		// enhanced forEach loop
		for(Object obj : any){
			System.out.print(obj + " ");
		}
		System.out.println("\n");
	}

	// main() method - to begin execution
	public static void main(String[] args) {

		// create ArrayList of Integer
		ArrayList<Integer> intList = new ArrayList<Integer>();

		// add to Integer list
		intList.add(10);
		intList.add(30);
		intList.add(70);
		intList.add(90);

		// invoke generics method with wildcard
		addArrayListValues(intList);
	}
}

Output:

10 30 70 90

1.3.1 Compile-time error for Lower-bounded wildcard:

2. Important point to remember w.r.t Generics wildcards:

  • Wildcards works only with Generics methods i.e.; it isn’t applicable to Generics classes
  • super keyword to specify lower bound works only with wildcards and it strictly doesn’t work with Type-parameter T
  • Take extra care while working with super keyword because it accepts only super classes of the specified type in Generics method
  • Whereas wildcard with extends keyword works very similar to Type-parameter T
  • Combination of wildcard bounded-types aren’t applicable while defining Generics method

Hope, you found this article very helpful. If you have any suggestion or want to contribute or tricky situation you faced during Interview hours, then share with us. We will include that code here.

Related Articles:

References:

Happy Coding !!
Happy Learning !!

Java 5 - Generics interview question and answers
Java 5 - Generics methods