Download the JDK
Search the Tutorials
Hide the TOC
Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
Introduction

> JDK 5.0 introduces several new extensions to the Java programming language. One of these is the introduction of generics.

> This trail is an introduction to generics. You may be familiar with similar constructs from other languages, most notably C++ templates. If so, you'll see that there are both similarities and important differences. If you are unfamiliar with look-a-alike constructs from elsewhere, all the better; you can start fresh, without having to unlearn any misconceptions.

> Generics allow you to abstract over types. The most common examples are container types, such as those in the Collections hierarchy.

> Here is a typical usage of that sort:

> >     List myIntList = new LinkedList(); // 1
> >     myIntList.add(new Integer(0)); // 2
> >     Integer x = (Integer) myIntList.iterator().next();  // 3

> The cast on line 3 is slightly annoying. Typically, the programmer knows what kind of data has been placed into a particular list. However, the cast is essential. The compiler can only guarantee that an `Object` will be returned by the iterator. To ensure the assignment to a variable of type `Integer` is type safe, the cast is required.

> Of course, the cast not only introduces clutter. It also introduces the possibility of a run time error, since the programmer may be mistaken.

> What if programmers could actually express their intent, and mark a list as being restricted to contain a particular data type? This is the core idea behind generics. Here is a version of the program fragment given above using generics:

> >     List<Integer> myIntList = new LinkedList<Integer>(); // 1'
> >     myIntList.add(new Integer(0)); // 2'
> >     Integer x = myIntList.iterator().next(); // 3'

> Notice the type declaration for the variable `myIntList`. It specifies that this is not just an arbitrary `List`, but a `List` of `Integer`, written `List<Integer>`. We say that `List` is a generic interface that takes a type parameter--in this case, `Integer`. We also specify a type parameter when creating the list object.

> Note, too, that the cast on line 3' is gone.

> Now, you might think that all we've accomplished is to move the clutter around. Instead of a cast to `Integer` on line 3, we have `Integer` as a type parameter on line 1'. However, there is a very big difference here. The compiler can now check the type correctness of the program at compile-time. When we say that `myIntList` is declared with type `List<Integer>`, this tells us something about the variable `myIntList`, which holds true wherever and whenever it is used, and the compiler will guarantee it. In contrast, the cast tells us something the programmer thinks is true at a single point in the code.

> The net effect, especially in large programs, is improved readability and robustness.

Previous page: Generics
Next page: Defining Simple Generics