Blogroll

An Introduction to Generics in Java – Part 1

Generics play an important role in the development of Java applications. They provide stronger type checks at compile time, reduce the amount of typecasting needed and help to develop algorithms/procedures that can be reused for multiple types. In this series I will try to write a short tutorial about them.

A typical Generics Use Case – Implementing a Sorting Algorithm

Rather than learning generics by definition, let’s try learning it from one simple use case – implementing Insertion Sort.

We all know how Insertion Sort works. We are given an array of elements. Then the algorithm removes one element from the array, repeat over the existing ones, find the appropriate place for the removed element, and then inserts it there.

Now what if we want to sort array of floats, or doubles? Or, array of some custom objects? Can we use the above implementation for those cases?

No. Period.

The above algorithm only sorts simple integers. It cannot sort doubles, or floats, because in Java you cannot pass array of doubles to a method which expects an array of integer. So, if you want to sort doubles or floats, you’ll have to write another implementation which will then sort an array of doubles.

This approach has some serious drawbacks. For one, you’ll now have to maintain two different sorting algorithms, just to ensure that they operate on different types, even though the algorithm to sort them is exactly the same. From the principles of good Object Oriented Design, we know that this is bad, really really bad.

So, how can we change this implementation so that it works for doubles, or better yet, works for any types which can be compared with each other? Let’s pause for a moment here and try to think it by ourselves.

Really, don’t go read the next section. Thinking about why we need, or should use a language feature will help us to truly master it and use it effectively in our application.

Generics to the Rescue!

Ok, so you thought it through, right? If this is the case, then carry on!

What we will do is that we will somehow parameterize the above class so that it will now take types as its argument. This way, we will pass a new type as its argument whenever we will create a new instance of this class, which will then enable us to use the above algorithm for that type!

This is exactly what generics do! They enable types to be parameters when defining classes, interfaces and methods! From the official Oracle Java tutorial page –

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs. The difference is that the inputs to formal parameters are values, while the inputs to type parameters are types.

Let’s see the implementation first, then we will slowly understand how to write generics in the code and what syntax to use –

Now, let’s dissect the above implementation to understand the syntax of generics –

Take a look at the first line, the class declaration. Notice the extra <E extends Comparable<E>>part which is new? This is the part which adds generic behavior to the previous implementation. Here, E is the type parameter. We will go into the syntax details in the next section.

Take a look at the elements declaration. After you declare a type parameter in the class declaration, you can then use it to declare a reference of that type. In our case, it’s an array.

Take a look at the condition check inside the while loop, in the sort method. It has been changed to use the implementation of the Comparable interface. Keep a note of this because it will be explained in a later post.

and voila! With the above changes we can now use this class for lots of different types, provided that they all are of non-primitive types (yes, Generics don’t support primitive types) and implement the Comparable interface (this is to make sure that the elements can be compared with each other).

Generics Declaration Syntax

To declare a class as a generic one, we use the following format –

class name<T1, T2, ..., Tn> { /* ... */ }

The portion delimited by angle brackets in the type parameter section where you define the type parameters (they are also called type variables sometimes). The above declaration specified n type parameters – T1, T2, ….., Tn, and is called a generic type declaration. A type variable can be anything – any class type, interface, array or anything else, provided that it’s a non-primitive type.

After you declare a class in the above way and specify a type parameter, you can then use it like any other type inside that class, subject to the following conditions –

You cannot create an instance of a type parameter.

You cannot declare any static field whose type matches a type parameter.

You cannot typecast or use instanceof operator with type parameters.

You cannot catch or throw objects of parameterized types.

I know that the example I’ve provided looks more complex than the simple declaration syntax above. Keep your patience, I will certainly explain it in a future post (if I don’t, you are given the permission to poke me with a stick).

So now we’ve seen a simple use case of Generics. Thankfully that wasn’t too complex to understand.

That’s it for today, folks. Hopefully I will write the next post of this series pretty soon. If anything in the current post seems difficult to understand, or if you find any errors, please feel free to comment in!