Bounded Types with Generics in Java

Last Updated : 3 Oct, 2026

Bounded type parameters in Java Generics restrict the types that can be used as arguments for a type parameter. They are useful when generic code needs to operate only on a specific type or its subtypes.

  • Bounds are specified using the extends keyword.
  • A type parameter can have a single bound or multiple bounds.

Declaration of Bounded Type Parameter

  • List the type parameter's name,
  • Along with the extends keyword
  • And by its upper bound. (which in the below example c is A.)

Syntax

<T extends superClassName>

Note: In generics, extends means that T can be any subclass of the specified type or the type itself. It sets an inclusive upper bound for the type parameter.

Example: Let’s take understand how to implement bounded types (extend superclass) with generics.

Java
class Bound<T extends A>
{
    private T objRef;
    
    public Bound(T obj){
        this.objRef = obj;
    }
    
    public void doRunTest(){
        this.objRef.displayClass();
    }
}

class A
{
    public void displayClass()
    {
        System.out.println("Inside super class A");
    }
}

class B extends A
{
    public void displayClass()
    {
        System.out.println("Inside sub class B");
    }
}

class C extends A
{
    public void displayClass()
    {
        System.out.println("Inside sub class C");
    }
}

public class BoundedClass
{
    public static void main(String[] args)
    {
        // Creating object of sub class C and passing it to Bound as a type parameter.
        Bound<C> bec = new Bound<C>(new C());
        bec.doRunTest();
        
        // Creating object of sub class B and passing it to Bound as a type parameter.
        Bound<B> beb = new Bound<B>(new B());
        beb.doRunTest();
        
        // similarly passing super class A
        Bound<A> bea = new Bound<A>(new A());
        bea.doRunTest();
    }
}

Output
Inside sub class C
Inside sub class B
Inside super class A

Now, we are restricted to only type A and its subclasses, So it will throw an error for any other type of subclasses.

Example: Bounded Type Parameters in Generics (T extends A) . Only classes that extend class A can be used as type arguments

Java
class Bound<T extends A>
{
    private T objRef;
    
    public Bound(T obj){
        this.objRef = obj;
    }
    
    public void doRunTest(){
        this.objRef.displayClass();
    }
}

class A
{
    public void displayClass()
    {
        System.out.println("Inside super class A");
    }
}

class B extends A
{
    public void displayClass()
    {
        System.out.println("Inside sub class B");
    }
}

class C extends A
{
    public void displayClass()
    {
        System.out.println("Inside sub class C");
    }
}

public class BoundedClass
{
    public static void main(String a[])
    {
        Bound<C> bec = new Bound<C>(new C());
        bec.doRunTest();
        
        Bound<B> beb = new Bound<B>(new B());
        beb.doRunTest();

        Bound<A> bea = new Bound<A>(new A());
        bea.doRunTest();
        
        Bound<String> bes = new Bound<String>(new String());
        bes.doRunTest();
    }
}

Output :

error: type argument String is not within bounds of type-variable T

Multiple Bounds

Multiple bounds restrict a type parameter to a class and one or more interfaces. The bounds are separated using the & operator.

Syntax:

<T extends ClassName & Interface1 & Interface2>

Note: Only one class can be specified in multiple bounds, and it must appear before any interface bounds.

Example: Bound Type Parameters using multiple bounds in Generics (T extends A & B)

Java
class Bound<T extends A & B>
{
    private T objRef;
    
    public Bound(T obj){
        this.objRef = obj;
    }
    
    public void doRunTest(){
        this.objRef.displayClass();
    }
}
interface B
{
    public void displayClass();
}

class A implements B
{
    public void displayClass()
    {
        System.out.println("Inside super class A");
    }
}
public class BoundedClass
{
    public static void main(String a[])
    {
        Bound<A> bea = new Bound<A>(new A());
        bea.doRunTest();
        
    }
}

Output
Inside super class A
Comment