Bounded type parameters expand on the capabilities of the compile time type safety that generics bring.
It does this by allowing us to restrict the
To add bounds, we use the extends
keyword followed by the Class or Interface type we want the type parameter to
Simple bounds
In this example, we restrict the type parameter arguments to be either Number
or one of its subtypes!
class MyBox<T extends Number> {
private T value;
public MyBox(T v) {
value = v;
}
public T get() {
return value;
}
public static void main (String[] args) {
MyBox<Integer> a = new MyBox<>(1);
MyBox<String> b = new MyBox<>("hehe");
}
}
Compilation Error!
type argument String is not within bounds of type-variable T MyBox<String> b = new MyBox<>(“hehe”);
Assignment of String
to the type parameter of MyBox
fails as the type parameter is bounded, meaning the argument must have a ‘is a’ relationship with Number
, as defined by <T extends Number>
.
Multiple Bounds
abstract class Animal{
protected int numberOfLimbs;
public Animal(int n) {
numberOfLimbs = n;
}
public static void main(String[] args) {
// This is fine because Dog has a 'is a' relationship with
// both Animal and CanBark
BarkingBox<Dog> a = new BarkingBox<>(new Dog());
// Whereas, this fails as Cat is not a CanBark
BarkingBox<Cat> b = new BarkingBox<>(new Cat());
}
}
class BarkingBox<T extends Animal & CanBark> {
private T value;
public BarkingBox(T v) {
value = v;
}
public T get() {
return value;
}
}
interface CanBark {
String bark();
}
class Cat extends Animal {
public Cat() {
super(4);
}
}
class Dog extends Animal implements CanBark {
public Dog() {
super(4);
}
@Override
public String bark() {
return "woof!";
}
}
Compilation Error!
type argument Cat is not within bounds of type-variable T BarkingBox<Cat> b = new BarkingBox<>(new Cat());