Home arrow Java arrow Page 5 - 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 - Erasure
(Page 5 of 5 )


Let's take a look at a compiled generic class: our friend, List. We can do this easily with the javap command:

  % javap java.util.List

  public interface java.util.List extends java.util.Collection{
public abstract boolean add(java.lang.Object);
public abstract java.lang.Object get(int);

The result looks exactly like it did prior to Java generics, as you can confirm with any older version of the JDK. Notably, the type of elements used with the add() and get() methods is Object. Now, you might think that this is just a ruse and that when the actual type is instantiated, Java will create a new version of the class internally. But that's not the case. This is the one and only List class and it is the actual runtime type used by all parameterizations of List, for example, List<Date> and List<String>, as we can confirm:

  List<Date> dateList = new ArrayList<Date>();
  System.out.println( dateList instanceof List ); // true!

But our generic dateList clearly does not implement the List methods just discussed:

  dateList.add( new Object() ); // Compile-time Error!

This illustrates the somewhat schizophrenic nature of Java generics. The compiler believes in them, but the runtime says they are an illusion. What if we try something a little more sane looking and simply check that our dateList is a List<Date>:

  System.out.println( dateList instanceof List<Date> ); // Compile-time Error!
  // Illegal, generic type for instanceof

This time the compiler simply puts its foot down and says, "no." You can't test for a generic type in an instanceof operation. Since there are no actual differentiable classes for different parameterizations of List at runtime, there is no way for the instanceof operator to tell the difference between one incarnation of List and another. All of the generic safety checking was done at compile time and now we're just dealing with a single actual List type.

What has really happened is that the compiler has erased all of the angle bracket syntax and replaced the type variables in our List class with a type that can work at runtime with any allowed type: in this case, Object. We would seem to be back where we started, except that the compiler still has the knowledge to enforce our usage of the generics in the code at compile time and it can, therefore, handle the cast for us. If you decompile a class using a List<Date> (the javap command with the -c  option shows you the bytecode, if you dare), you will see that the compiled code actually contains the cast to Date, even though we didn't write it ourselves.

We can now answer one of the questions we posed at the beginning of the section ("Why can't I implement what appear to be two different generic interfaces in one class?"). We can't have a class that implements two different generic List instantiations because they are really the same type at runtime and there is no way to tell them apart:

  public abstract class DualList implements List<String>, List<Date> { }
  // Error: java.util.List cannot be inherited with different arguments:
  //   <java.lang.String> and <java.util.Date>

Please check back next week for the continuation of this article.

DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

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