How to choose Upper & Lower bounds in Java Generics?

Vaibhav Singh
Javarevisited
Published in
3 min readJun 18, 2020

--

Most of the Java developers have an unfounded fear of Generics(or I call it fear of Unknown :D) due to lack of understanding. And if by chance, they overcome that fear, they start fearing the upper and lower bound. This blog is my sincere effort to explain the concept in a simplistic way.

Java Generics

What is the use of Upper & Lower Bound?

These are used to relax the restriction on a variable.

Upper Bound WildCards (? extends Type)

This restricts the unknown type to be a specific type or sub-type. This can be explained with the following example :

Lets Assume function can accept Number and its sub-types , the sample signature should be like this :

public void myFunction(List<? extends Number> list)
{ /* some implementation */}

Lower Bound Wildcards(? super Type.)

This restricts the unknown type to be a specific type or super-type of that type. This can be explained with the following example:

Lets Assume function can accept Integer and its super-types , the sample signature should be like this :

public void myFunction(List<? super Integer> list)
{ /* some implementation */}

So the above function accepts List<Integer> & List<Number> but NOT List<Double> .

Multiple Bounds

<T extends C & I> indicates that the caller can specify any type that extends C and I. This can be explained as below :

class MultipleBound<T extends A & B>
{
private T objRef;

public MultipleBound(T obj)
{
this.objRef = obj;
}

public void run()
{
this.objRef.execute();
}
}
interface B
{
public void execute();
}
public class A implements B
{
public void execute()
{
System.out.println("Inside class A");
}
}
public class BoundedClass
{
public static void main(String a[])
{
MultipleBound<A> obj= new MultipleBound<>(new A());
obj.run();
}
}

Segal’s law is an adage that states:

“A man with a watch knows what time it is. A man with two watches is never sure.”

When to Choose What ?

In order to decide which type of wildcard best suits the condition, let’s first classify the type of parameters passed to a method as in and out parameter.

  • in variable − An in variable provides data to the code. For example, copy(src, dest). Here src acts as in variable being data to be copied.
  • out variable − An out variable holds data updated by the code. For example, copy(src, dest). Here dest acts as in variable having copied data.

Guidelines for Wildcards(Get-Put Principle)

  • Upper bound wildcard − If a variable is of in category, use extends keyword with wildcard.
  • Lower bound wildcard − If a variable is of out category, use super keyword with wildcard.
  • Unbounded wildcard − If a variable can be accessed using Object class method then use an unbound wildcard.
  • No wildcard − If code is accessing variable in both in and out category then do not use wildcards.

Summary

Bounded wildcards are extremely useful in making flexible generic APIs. The biggest impediment to using bounded wildcards is the identification of the situation for lower/upper bounded wildcards.

The get-put principle can be used to determine which should be used.

Questions ? Suggestions ? Comments ?

--

--

Vaibhav Singh
Javarevisited

I am a #TechnologyEnthusiast #Coder #JavaProgrammer #Blogger (https://linqz.io) #Dreamer. In my free time I love to #Cook, #ShareStories & #VolunteerForPoor.