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.

A bounded type parameter is a mechanism in Java Generics that restricts the types permitted as arguments for a parameterized type. By defining an upper bound, the compiler enforces type safety by ensuring only specific class hierarchies or interface implementations are accepted, while simultaneously granting the generic type access to the methods defined by the bounding type.

Upper Bounded Type Parameters

An upper bound restricts a type parameter to a specific class or interface, or any of its subtypes. In generic type declarations, the extends keyword is used universally to denote an upper bound, regardless of whether the bounding type is a class or an interface.
// T must be Number or a subclass of Number (e.g., Integer, Double)
public class NumericContainer<T extends Number> {
    private T value;

    public NumericContainer(T value) {
        this.value = value;
    }

    public double getDoubleValue() {
        // Safe to call Number methods because T is bounded by Number
        return value.doubleValue(); 
    }
}

Multiple Bounds (Intersection Types)

A type parameter can be constrained by multiple bounds using the & operator. The generic type argument must be a subtype of all specified bounds. Due to Java’s single inheritance model, a multiple bound can contain at most one class. If a class is specified, it must be the first bound in the intersection type, followed by any number of interfaces.
// T must extend the class Number AND implement both Comparable and Serializable
public class ComplexContainer<T extends Number & Comparable<T> & Serializable> {
    private T item;
    
    public int compareToAnother(T other) {
        // Safe to call Comparable methods
        return item.compareTo(other);
    }
}

Distinction: Type Parameters vs. Bounded Wildcards

According to the Java Language Specification, type parameters are distinct from wildcards. Type parameters are the variables declared in a generic class or method signature (e.g., the T in class Box<T>) and can only accept upper bounds. Wildcards (?), conversely, are used as type arguments in parameterized types (e.g., the ? in List<?>). Unlike type parameters, wildcards support both upper and lower bounds to establish covariance and contravariance. Upper Bounded Wildcards (? extends Type) Establishes covariance. It represents an unknown type argument that is a specific type or a subtype of that type.
// Accepts a List of Number, List of Integer, List of Double, etc.
public void processNumbers(List<? extends Number> list) {
    Number n = list.get(0); // Safe to read as Number
    // list.add(1); // Compilation error: Cannot write to upper-bounded wildcard
}
Lower Bounded Wildcards (? super Type) Establishes contravariance. It represents an unknown type argument that is a specific type or a supertype of that type. Lower bounds use the super keyword and cannot be applied to standard type parameters.
// Accepts a List of Integer, List of Number, or List of Object
public void addIntegers(List<? super Integer> list) {
    list.add(10); // Safe to write Integer or its subtypes
    // Integer i = list.get(0); // Compilation error: Cannot safely read as Integer
}

Type Erasure and Bounds

During compilation, Java applies type erasure to generic parameters. If a type parameter is bounded, the compiler replaces the type parameter with its first bound. If there are multiple bounds, the compiler inserts necessary type casts for methods belonging to the subsequent bounds.
// Pre-erasure source code
public class Node<T extends Comparable<T>> {
    private T data;
    public T getData() { return data; }
}

// Post-erasure bytecode equivalent
public class Node {
    private Comparable data; // T is replaced by its first bound
    public Comparable getData() { return data; }
}
Master Java with Deep Grasping Methodology!Learn More