Wildcards Generics (Upper bounded, lower bounded, and unbounded)

Wildcard generics in Java provide flexibility in working with generic types by allowing unknown or partially constrained types in method parameters, return types, or fields. They are denoted by the ? symbol and are useful when you need to work with a range of types without specifying an exact type.

Important Concepts of Wildcard Generics

  • Purpose: Wildcards allow methods or classes to operate on generic types with unknown or loosely defined type parameters, enhancing flexibility while maintaining type safety.
  • Syntax: The ? represents an unknown type, used in places like List<?>, List<? extends T>, or List<? super T>.
  • Use Cases: Common in APIs like collections, where methods need to accept a variety of generic types (e.g., List<?> for any list).

Types of Wildcards

Unbounded Wildcard (?)

  • Represents any type, equivalent to ? extends Object.
  • Used when you don’t care about the specific type but need to work with the generic structure.
  • Example: List<?> can hold a List<Integer>, List<String>, etc.
  • Limitation: You can’t add elements (except null) because the type is unknown, but you can read as Object.

Upper-Bounded Wildcard (? extends T)

Restricts the type to T or its subtypes.

  • Used for read-heavy operations (e.g., iterating over a list of numbers).
  • Example: List<? extends Number> accepts List<Integer>, List<Double>, etc.
  • Limitation: You can read elements as T (e.g., Number), but you can’t add elements (except null) due to type uncertainty.

Lower-Bounded Wildcard (? super T)

  • Restricts the type to T or its supertypes.
  • Used for write-heavy operations (e.g., adding elements to a list).
  • Example: List<? super Integer> accepts List<Integer>, List<Number>, or List<Object>.
  • Limitation: You can add T or its subtypes, but reading yields Object unless you know the exact type.

Program

Demonstrating wildcard generics, focusing on upper- and lower-bounded wildcards

import java.util.ArrayList;
import java.util.List;

public class WildcardDemo {
    // Method using upper-bounded wildcard to sum numbers
    public static double sumList(List<? extends Number> list) {
        double sum = 0.0;
        for (Number num : list) {
            sum += num.doubleValue();
        }
        return sum;
    }

    // Method using lower-bounded wildcard to add integers
    public static void addIntegers(List<? super Integer> list, int count) {
        for (int i = 1; i <= count; i++) {
            list.add(i);
        }
    }

    public static void main(String[] args) {
        // Upper-bounded wildcard example
        List<Integer> integers = new ArrayList<>(List.of(1, 2, 3));
        List<Double> doubles = new ArrayList<>(List.of(1.5, 2.5, 3.5));
        System.out.println("Sum of integers: " + sumList(integers)); // 6.0
        System.out.println("Sum of doubles: " + sumList(doubles));   // 7.5

        // Lower-bounded wildcard example
        List<Number> numbers = new ArrayList<>();
        List<Object> objects = new ArrayList<>();
        addIntegers(numbers, 3);
        addIntegers(objects, 2);
        System.out.println("Numbers list: " + numbers); // [1, 2, 3]
        System.out.println("Objects list: " + objects); // [1, 2]
    }
}

/*
Sum of integers: 6.0
Sum of doubles: 7.5
Numbers list: [1, 2, 3]
Objects list: [1, 2]
*/
Scroll to Top