Java 5 – Bounded Types in Generics

In the previous article, we have discussed on Generics class which helps to instantiate with only particular type-parameter and this way Generics classes provides type-safety

1. Unbounded Types:

  • But, what happens is that, it allows to instantiate with any of the following types,
    1. Wrapper-types
    2. Reference-types like class/interface
  • Actually, we don’t have control over restricting a Generics class to limit itself and such type of Generics classes are called unbounded types
  • For example, in the below GenericsClass.java allows any type to be replaced with type-parameter T

GenericsClass.java

package in.bench.resources.generics.example;

public class GenericsClass<T> {

	// member variable
	T t;

	//	1-arg constructor
	public GenericsClass(T t) {
		super();
		this.t = t;
	}

	// getter & setter
	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}
}

TestGenerics.java

package in.bench.resources.generics.example;

public class TestGenerics {

	public static void main(String[] args) {

		// 1. instantiate Generics class with String
		GenericsClass<String> gcStr =
				new GenericsClass<String>("TestString");

		// 2. instantiate Generics class with Float
		GenericsClass<Float> gcFlt =
				new GenericsClass<Float>(25.306f);

		// 3. instantiate Generics class with Double
		GenericsClass<Double> gcDbl =
				new GenericsClass<Double>(20152.137);

		// 4. instantiate Generics class with Integer
		GenericsClass<Integer> gcInt =
				new GenericsClass<Integer>(64);
	}
}

Explanation:

  • In the above example GenericsClass.java, we have specified Type-parameter without bound, which allows to use this class with any of the valid type like wrapper-type or reference-types
  • In TestGenerics.java, we have instantiated GenericsClass with 4 different objects
  • Here, we have used String type and 3 different wrapper-types such as Integer, Float and Double
  • Hence, defining Generics class with just Type-parameter T is known as unbounded-types, as it allows any class/interface to be replaced with Type-parameter T

2. Bounded Types:

  • Putting limit to Type-parameter for specifying particular range while defining Generics class is known as Bounded types or Bounded classes
  • To define bound, we can use extends keyword as per below syntax
  • Syntax:
<T extends referenceType>
  • This referenceType can be either class/interface
  • If referenceType is a class, then Type-parameter T can be replaced by either class or one of its sub-classes
  • Similarly, if referenceType is an interface, then Type-parameter T can be replaced by either interface or one of its implementation classes
  • Let us see one example based on bounded-types

GenericsClass.java

package in.bench.resources.generics.example;

public class GenericsClass<T extends Number> {

	// member variable
	T t;

	//	1-arg constructor
	public GenericsClass(T t) {
		super();
		this.t = t;
	}

	// getter & setter
	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}
}

TestGenerics.java

Explanation:

In the above GenericsClass.java example,

  • We have specified Type-parameter with upper-bound as Number which allows to accept either Number class or its sub-classes like Integer, Double or Float, etc.
  • But in TestGenerics.java, when we tried to instantiate GenericClass with other types, a compile-time error is thrown stating “Bound mismatch
  • At line no. 14 & 20, compiler doesn’t complain anything because both Float & Integer are sub-classes of Number
  • Whereas at line no. 8 & 17 compiler throws error for Bound mismatch as shown in the above screen-capture because neither String nor StringBuffer is a sub-class of Number class
  • Note: we can define bounded type with extends keyword only, no other keyword are allowed

3. Combination of Bounded Types:

Till now, we have seen bounded types with bound of one class but actually we can use combination of class & interfaces, like possible combination are listed below,

  1. Maximum of one class
  2. Maximum of one class & one interface
  3. Multiple interfaces
  4. Maximum of one class & multiple interfaces

Note: while defining combination of bounded types, use ampersand (&) sign to separate class and interfaces

All above declared combination are valid for bounded types using extends keyword but following are invalid declaration and compiler throws error

  1. Multiple classes (i.e.; 2 or more classes)
  2. First-up interface and then class (sequence does matter)

3.1 Valid combination for bounded types:

  1. One class
  2. One class & one interface
  3. Multiple interfaces
  4. One class & multiple interfaces

3.2 Invalid combination for bounded types:

  1. Multiple classes (i.e.; 2 or more classes)
  2. First-up interface and then class (sequence does matter in combination bounded-types)

Hope, you found this article very helpful. If you have any suggestion or want to contribute or tricky situation you faced during Interview hours, then share with us. We will include that code here.

Related Articles:

References:

Happy Coding !!
Happy Learning !!

Java 5 - Generics methods
Java 5 - Generics classes