Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An upper bounded wildcard restricts the unknown type in a generic instantiation to be a specific type or any of its subtypes. It establishes covariance in Java’s generic type system, allowing a generic type to accept a parameterized type that is a descendant of a defined upper bound.

Syntax

The upper bounded wildcard is declared using the ? character, followed by the extends keyword, and the bounding class or interface.
<? extends SuperType>

Type System Mechanics

By default, Java generics are invariant. For example, List<Integer> is not a subtype of List<Number>, even though Integer is a subtype of Number. Applying an upper bounded wildcard makes the generic type covariant. This means List<Integer>, List<Double>, and List<Number> are all valid subtypes of List<? extends Number>.
List<Integer> integers = new ArrayList<>();
List<Double> doubles = new ArrayList<>();

// Covariant assignments
List<? extends Number> numbers1 = integers; 
List<? extends Number> numbers2 = doubles;  

Read and Write Constraints

The primary technical implication of using an upper bounded wildcard dictates how the compiler handles read and write operations on the generic structure.

Read Operations (Safe)

When retrieving an element from a structure defined with an upper bounded wildcard, the compiler guarantees that the object will be an instance of the upper bound type (or a subtype thereof). Therefore, it is strictly type-safe to read the element as the upper bound type.
List<? extends Number> boundedList = getSomeNumberList();

// The compiler guarantees the returned element is at least a Number
Number num = boundedList.get(0); 

Write Operations (Prohibited)

Writing to a structure defined with an upper bounded wildcard is strictly prohibited by the compiler, with the sole exception of the null literal. Because the wildcard represents an unknown specific subtype of the bound, the compiler cannot verify type safety at compile time. If List<? extends Number> is currently pointing to a List<Integer>, allowing the addition of a Double would cause heap pollution. To prevent this, the compiler disables all parameterized insertions.
List<Integer> intList = new ArrayList<>();
List<? extends Number> boundedList = intList;

// Compilation Errors: The compiler does not know the exact subtype
// boundedList.add(Integer.valueOf(1)); // ERROR
// boundedList.add(Double.valueOf(1.0)); // ERROR
// boundedList.add(new Object());        // ERROR

// Permitted, as null belongs to any reference type
boundedList.add(null); 

Interface vs. Class Bounds

The extends keyword in an upper bounded wildcard applies universally to both classes and interfaces. There is no implements keyword used in wildcard bounds.
// Valid whether Runnable is an interface or a class
List<? extends Runnable> tasks; 
Note: Unlike generic type parameters (e.g., <T extends ClassA & InterfaceB>), wildcards do not support multiple bounds. Syntax like <? extends ClassA & InterfaceB> is invalid in Java.
Master Java with Deep Grasping Methodology!Learn More