Home arrow Java arrow Page 2 - Generics in Java

Generics in Java

Generics are the most important change to the Java language in a long time, possibly since it was created. They make reusable Java code easier to write and read. This article, the first in a series, was excerpted from chapter eight of the book Learning Java, third edition, written by Patrick Niemeyer and Jonathan Knudsen (O'Reilly; ISBN: 0596008732). Copyright 2006 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

Author Info:
By: O'Reilly Media
Rating: 4 stars4 stars4 stars4 stars4 stars / 11
May 10, 2007
  1. · Generics in Java
  2. · Containers: Building a Better Mousetrap
  3. · Enter Generics
  4. · There Is No Spoon
  5. · Erasure

print this article

Generics in Java - Containers: Building a Better Mousetrap
(Page 2 of 5 )


In an object-oriented programming language like Java, polymorphism means that objects are always to some degree interchangeable. Any child of a type of object can serve in place of its parent type and, ultimately, every object is a child of java.lang.Object, the object-oriented "Eve," so to speak. It is natural, therefore, for the most general types of containers in Java to work with the type Object so that they can hold most anything. By containers, we mean classes that hold instances of other classes in some way. The Java Collections Framework is the best example of containers. A List, for example, holds an ordered collection of elements of type Object. A Map holds an association of key-value pairs, with the keys and values also being of the most general type, Object. With a little help from wrappers for primitive types, this arrangement has served us well. But (not to get too Zen on you), in a sense, a "collection of any type" is also a collection of no type," and working with Objects pushes a great deal of responsibility onto the user of the container.

It's kind of like a costume party for objects where everybody is wearing the same mask and disappears into the crowd of the collection. Once objects are dressed as the Object type the compiler can no longer see the real types and loses track of them. It's up to the user to pierce the anonymity of the objects later using a type cast. And like attempting to yank off a party-goer's fake beard, you'd better have the cast correct or you'll get an unwelcome surprise.

  Date date = new Date();
  List list = new ArrayList();
  list.add( date );
  Date firstElement = (Date)list.get(0); // Is the cast correct? Maybe.

The List interface has an add() method that accepts any type of Object. Here, we assigned an instance of ArrayList, which is simply an implementation of the List interface, and added a Date object. Is the cast in this example correct? It depends on what happens in the elided "..." period of time.

Can Containers Be Fixed?

It's natural to ask if there is a way to make this situation better. What if we know that we are only going to put Dates into our list? Can't we just make our own list that only accepts Date objects, get rid of the cast, and let the compiler help us again? The answer, surprisingly perhaps, is no. At least, not in a very satisfying way.

Our first instinct may be to try to "override" the methods of ArrayList in a subclass. But of course, rewriting the add() method in a subclass would not actually override anything; it would add a new overloaded method.

  public void add( Object o ) { ... }   
  public void add( Date d ) { ... } // overloaded method

The resulting object still accepts any kind of object--it just invokes different methods to get there.

Moving along, we might take on a bigger task. For example, we might write our own DateList class that does not extend ArrayList but delegates the guts of its methods to the ArrayList implementation. With a fair amount of tedious work, that would get us an object that does everything a List does but works with Dates. However, we've now shot ourselves in the foot because our container is no longer an implementation of List and we can't use it interoperably with all of the utilities that deal with collections, such as Collections.sort(), or add it to another collection with the CollectionaddAll() method.

To generalize, the problem is that instead of refining the behavior of our objects, what we really want to do is to change their contract with the user. We want to adapt their API to a more specific type and polymorphism doesn't allow that. It would seem that we are stuck with Objects for our collections. But this is where generics come in.

blog comments powered by Disqus

- Java Too Insecure, Says Microsoft Researcher
- Google Beats Oracle in Java Ruling
- Deploying Multiple Java Applets as One
- Deploying Java Applets
- Understanding Deployment Frameworks
- Database Programming in Java Using JDBC
- Extension Interfaces and SAX
- Entities, Handlers and SAX
- Advanced SAX
- Conversions and Java Print Streams
- Formatters and Java Print Streams
- Java Print Streams
- Wildcards, Arrays, and Generics in Java
- Wildcards and Generic Methods in Java
- Finishing the Project: Java Web Development ...

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 

Developer Shed Affiliates


© 2003-2019 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials