We can bound the type parameter for a particular range. Such type of types are called bounded types.

We can achieve this by using extends keyword.

Example:1

class Gen<T>{
}

Here we can pass any types as the type parameter and there are no restrictions.

Gen<String> g1 = new Gen<String>();
Gen<Integer> g2 = new Gen<Integer>();

Example:2

class Gen<T extends X>

If ‘X’ is a class then any type which is the child class of ‘X’ is allowed as the type parameter.
If ‘X’ is an interface then any type which is the implementation class of ‘X’ is allowed as the type parameter.

Example:3

class Gen<T extends Number>{
}

In this case as the type parameter we can take either number or it’s child classes.

Gen<Integer> g1 = new Gen<Integer>();//Valid
Gen<String> g2 = new Gen<String>();//In valid
//Because type parameter String is not with in it's bound

Example:4

class Gen<T extends Runnable>{
}

In this case,As the type parameter we can take any implementation class of Runnable interface.

Gen<Thread> t1 = new Gen<Thread>();

Because Thread is implementation class of Runnable

Gen<String> t2 = new Gen<String>();//Invalid

Because String is not implementation class of Runnable interface.

In generics,we have only extends keyword and there is no implements keyword. It’s purpose is also survived by using extends keyword only.

Example:

class Generic<T extends Number> {
	T ob;

	Generic(T ob) {
		this.ob = ob;
	}

	void show() {
		System.out.println("The int value is :" + ob.intValue());
	}
}

class GenericDemo {
	public static void main(String arg[]) {
		Generic<Integer> t1 = new Generic<Integer>(new Integer(10));
		t1.show();
		Generic<Double> t2 = new Generic<Double>(10.5);
		t2.show();
		//Generic<String> t3 = new Generic<String>("Java");//Invalid
		//t3.show();
	}
}
/*
Output:
The int value is :10
The int value is :10
*/