While writing generic code you can also use a question mark (?) as type which represents an unknown type and known as wildcard in Java generics.
WildCard in Java generics and class relationship
You can use wildcards to create a relationship between generic classes or interfaces.
In case of non-generic classes
class A { /* ... */ } class B extends A { /* ... */ }
You can assign reference of child class to parent class.
B b = new B(); A a = b;
But the same assignment does not apply to generic types.
List<B> lb = new ArrayList<>(); List<A> la = lb; // compile-time error
So, List<B> is not the subtype of List<A> even if A is the parent class.
You can also understand it using the list of integers (List<Integer>) and list of numbers (List<Number>) where Number is the parent class of Integer but List<Integer> is not a subtype of List<Number> in fact, these two types are not related. The common parent of List<Number> and List<Integer> is List<?>. List of unknown type that could be a List<Integer>, List<A>, List<String> and so on.
Using this knowledge of common parent of two generic classes we’ll see how to create a bounded relationship between two generic classes (or interfaces) using three types of wildcards.
Types of wildcards in Java Generics
Based on the limit you want to impose on the relationship between two generic classes there are three types of wildcards.
- Upper bounded wildcards
- Lower bounded wildcards
- Unbounded wildcards
Upper bounded wildcards
To declare an upper-bounded wildcard, use the wildcard character ('?'), followed by the extends keyword, followed by the type that acts as upper bound. Upper bound wildcard matches the upper bound type or any of its subclasses.
For example List<? extends Number> matches a list of type Number or any of its subclasses i.e. List<Integer>, List<Double>, List<Number>.
Upper bounded wildcard Java example
Suppose you want to write a method that can add all the elements of the passed list. Since you have to add the elements so List should have elements of type Integer, Float, Double since Number is the super class for all these wrapper classes so you can create an upper bound using Number class.
import java.util.Arrays; import java.util.List; public class WildCard { public static void main(String[] args) { List<Integer> li = Arrays.asList(1, 2, 3, 4); System.out.println("sum = " + addListElements(li)); //List<Double> List<Double> ld = Arrays.asList(1.1, 2.2, 3.3, 4.4); System.out.println("sum = " + addListElements(ld)); } public static double addListElements(List<? extends Number> list){ double s = 0.0; for (Number n : list) { s += n.doubleValue(); } return s; } }Output
sum = 10.0 sum = 11.0
Lower bounded wildcards
A lower bounded wildcard is expressed using the wildcard character ('?'), following by the super keyword, followed by its lower bound. For example
<? super A>
A lower bounded wildcard restricts the unknown type to be a specific type or a super type of that type. For example you want to write a method that works on lists of Integer and the supertypes of Integer, such as Integer, Number, and Object then you would specify a lower bounded wildcard like this-
List<? super Integer>
Lower bounded wildcards Java example
Suppose you want to write a method that can insert integers to the end of a list and that can be a List of Object, List of Number or List of Integer then you can create a lower bound using Integer class.
import java.util.ArrayList; import java.util.List; public class WildCard { public static void main(String[] args) { // with List<Object> List<Object> lo = new ArrayList<Object>(); insertNumbers(lo); // with List<Number> List<Number> ln = new ArrayList<Number>(); insertNumbers(ln); // with List<Integer> List<Integer> li = new ArrayList<Integer>(); insertNumbers(li); } public static void insertNumbers(List<? super Integer> list) { for (int i = 1; i <= 10; i++) { list.add(i); } System.out.println("Elements in List- " + list); } }Output
Elements in List- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Elements in List- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Elements in List- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Unbounded wildcards in Java generics
The unbounded wildcard type is specified using the wildcard character (?).
For example, List<?> represents a list of unknown type.
Unbounded wildcard Java exampleSuppose you want to write a method that can print elements of a List of any type then you should use List<?> as method argument. Using List<Object> won’t work as List<Integer>, List<String>, List<Double> are not subtypes of List<Object>.
import java.util.Arrays; import java.util.List; public class WildCard { public static void main(String[] args) { // With List<Integer> List<Integer> li = Arrays.asList(5, 6, 7); printListElements(li); // With List<Double> List<Double> ld = Arrays.asList(1.2, 3.8, 8.2); printListElements(ld); } public static void printListElements(List<?> list){ for (Object e : list){ System.out.print(e + " "); } System.out.println(); } }Output
5 6 7 1.2 3.8 8.2That's all for the topic Java Generics - WildCards. If something is missing or you have something to share about the topic please write a comment.
You may also like
- Java Generics - Bounded Type Parameters
- Java Generics - Type Erasure
- Object Cloning in Java Using clone() Method
- Java String valueOf() Method With Examples
- Java CompletableFuture With Examples
- How to Get The Last Modified Date of a File in Java
- Spring Boot + Spring Data JPA + MySQL + Spring RESTful
- Shuffle Phase in Hadoop MapReduce
No comments:
Post a Comment