Java

Making the Most of Java 5: Exploring Generics

Tagged:  

Erasure aside, the addition of generics to Java (see intro here) brings added dimension to using types in the language. The most obvious application of generics is the ability to declare homogeneous Collection types, such as Collection<String>, but there are less obvious ones as well. I'll explore some of these in this article.

Type Inference

But first, a little diversion. Generics can be used both at the class level and at the method level in Java. Let's suppose we have a generic method like so:

public <T> T getSomething() { ... }

What happens if we do an assignment to a String?

String s = getSomething();

It compiles just fine. The same is true of the following:

Integer i = getSomething();

What is going on here? As you may have guessed, generic methods have an ability to do type inference, that is, they are able to figure out the type from the context of its use in an assignment expression. Quite a new wrinkle for an explicitly-typed language like Java.

If you define a generic type for a parameter to the method getSomething() that also uses <T>, the type defined by the parameter takes "precedence" over assignment inference.

Type-Inferred Factory Method

As Joshua Bloch pointed out in his "Effective Java Reloaded" presentation at JavaOne 2007, you can use this type inference to simplify the creation of complex generic types using a static factory method. Adding a method to the java.util.HashMap class like

public static <K,V> HashMap<K,V> newInstance() {
     return new HashMap<K,V>();
}

simplifies the creation of a complex HashMap object from

Map<String,List<Integer>> map = new HashMap<String,List<Integer>>();

to a much easier-to-read form like

Map<String,List<Integer>> map = HashMap.newInstance();

Type inference makes this possible.

Type-Safe Factory Method

Often factory methods will have a very general applicability, and so in earlier versions of Java, were forced to return an Object which was expected to be cast to the correct type. A good example of this is the java.lang.reflect.Proxy class which has the method:

public static Object newProxyInstance(ClassLoader loader,
     Class<?>[] interfaces,
     InvocationHandler h) 

Assuming that we only want to use the current ClassLoader and we are proxying using only a single interface, we can genericize this method to the following:

public static <T> T newProxyInstance(Class<T> interface, 
     InvocationHandler h)

(One could also genericize the InvocationHandler class with the generic type <T>, as well, so that the first argument of its invoke method was the correct type). Here interface argument is also functioning as a "type token", providing a guarantee that the factory method will return an instance of the correct type and the implementer with the means to do so (via the cast()). Since the type of the Class parameter passed in determines the type of <T>, it acts as a kind of "hook" to determine the type of the return value. Thus this method will not need to have its return value explicitly cast, and will never throw a ClassCastException.

Another great example of this technique are the various bind() methods for the Binder class in the Google Guice library. The type passed into the bind() method is "hooked" via a generic type to the type passed into the various chained to(), toProvider(), toInstance(), and annotatedWith() methods. Hence a "line of configuration" in a Google Guice Module that would define the dependency injection for a Collection interface would look like:

binder.bind(Collection.class).to(ArrayList.class);

Thanks to the use of a generic type, the parameter to the method to() is guaranteed to be of an assignable type to that of the method bind().

Guarantee of Behavior

A little-known part of the Generics specification is the ability to define conjunctive types, that is, multiple types separated by an '&' operator, when defining a generic bounded type. You can use this to make sure that a parameter to a method implements specific interfaces. For example, let's say that you have a method that takes an implementation of a certain interface MyInterface.

public void doSomething(MyInterface onObject) { ... }

Let's also say that you want the passed-in parameter to also implement java.lang.Comparable and java.io.Serializable so that you could sort and serialize the parameter in the method. How would you do this? Well, you could put guard code in your method and throw an IllegalArgumentException--and document this well--but compile-time errors are much preferable to runtime ones. This is where conjunctive generic types come to the rescue...you can change this method to the following:

public <T extends MyInterface & Comparable<T> & Serializable> 
     void doSomething(T onObject)

Now the caller of the method will get a compile error if they try to pass in an implementation of MyInterface that does not also implement the other two interfaces.

Conclusion

Despite some annoyances to the generics implementation in Java (read: erasure), Generics do bring an extra layer to the type safety of the language that can be used in new and creative ways. Once you get past the gotchas, they make your Java programs safer.

Tatami integrates the Google Web Toolkit and the DOJO framework

The Tatami project is an attempt to integrate the Google Web Toolkit (GWT) and the DOJO JavaScript framework. Tatami pulls in DOJO's rich widgets and utilities (like fisheye, slider, drag and drop functionality) and makes them accessible to the GWT as widgets and helpers. Tatami is compatible with the GWT 1.4 final version.

Check out the demo (may run slowly because files are being served from SVN)

Last month's release of Tatami-1.1 contained some new features, they are:

* DOJO 1.0 wrapped

* DropdownDatePicker and DropdownTimePicker with validation.

* Slider with labels an rule mark.

* The GFX package of DOJO wrapped. (Circle, Rectangle, Path, scaling...)

Visit the Tatami project homepage.

Top 5 GWT Libraries

Tagged:  

GWTSite held a contest asking users to vote for their favorite GWT third-party library, and as a result have compiled their own list of the top five most popular GWT third-party libraries.

Here they are:

5. Hibernate4gwt
Bruno Marchesson
For any Hibernate users out there, Hibernate4gwt allows you to painlessly use your Hibernate POJOs with GWT.

4. Gwittir
Robert Cooper and Charlie Collins
The Gwittir project provides a lot of interesting modules for your GWT projects including data-binding, animation, introspection, and more.

3. GWT-SL
George Georgovassilis
As the name implies, the GWT Server Library is it is a server-side library for GWT that focuses on providing Spring Framework integration by allowing you to expose your Spring beans as RPC services. It also provides integration with the hibernate4gwt library.

2. GWT-Ext
Sanjiv Jivan
GWT-Ext is a really nice looking GWT widget library that is closely integrated with the Ext JS library. Take a look at the GWT-Ext Showcase Demo.

1. MyGWT
Darrell Meyer
mygwt
MyGWT was the overwhelming favorite in the contest with almost half the vote. It is a pure GWT widget library which shares the Ext JS L&F to create a polished set of widgets for use in your GWT applications. Take a look at the MyGWT Explorer Demo.

Honorable mentions: gwt-dnd, gwt-log, gwt-maven, gwtwindowmanager, gwt-math

Click here to read the original post on GWT Site.

Let us know which GWT library you prefer.

Snipplr - a public source code repository

Snipplr is a public source code repository that gives you a place to store and organize all the little pieces of code that you use each day and It lets you share your code snippets with other coders and designers.

Snipplr was designed by Sitening, a Nashville Web Design company originally to store their code snippets in one place. They currently have around 3605 snippets in the following categories:
* ActionScript
* ActionScript 3
* Apache
* AppleScript
* ASP
* Assembler
* Bash
* C#
* C++
* Cold Fusion
* CSS
* Diff
* Emacs Lisp
* eZ Publish
* Forth
* Fortran
* Groovy
* HTML
* Java
* JavaScript
* Lisp
* Lua
* MatLab
* NewtonScript
* Objective C
* Open Firmware
* Other
* Pascal
* Perl
* PHP
* PicBasic
* Python
* Rails
* Regular Expression
* Ruby
* SmallTalk
* Smarty
* SML
* SQL
* SVN
* TCL
* TYPO3
* VB.NET
* VHDL
* Visual Basic
* W-Language
* XML

Click here to visit to the Snipplr code repository and let us know what you think.

Choosing a Development Framework

Over at Smashing Magazine they have put together a good round up of Development Frameworks. The post goes over the most popular frameworks for each language. The post also gives tips on what framework is best for you and has a brief over view of the Model View Controller (MVC) design pattern.

Below is an excerpt from the JavaScript frameworks.

JavaScript

  • Prototype is a JavaScript framework that serves as a foundation for other JavaScript frameworks. Don’t be fooled however, as Prototype can stand on its own.

  • script.aculo.us is built on the Prototype framework and has found its way into many high-profile sites including Digg, Apple, and Basecamp. The documentation is clear, and has an easy learning curve. However, compared to other JavaScript frameworks it is larger in size.

    Script.aculo.us

  • Mootools is a compact, modular, object-oriented JavaScript framework with impressive effects and Ajax handling. The framework is for advanced users as the learning curve is rather steep.

  • jQuery continues to rise in popularity due to its extensive API and active development. jQuery is a great balance of complexity and functionality.

  • For ASP.NET developers you can’t beat the ASP.NET AJAX framework which is built into the .NET Framework as of 3.5, but you can also download it for previous versions. The amount of documentation, examples, and community continues to increase. There are controls that you can simply drag-and-drop an update panel on an ASPX page and process Ajax!

    ASP.NET

Further JavaScript Frameworks

  • The Yahoo! User Interface Library - Yahoo! released its impressed JavaScript library with incredible amounts of documentation.
  • Ext JS - Originally built as an add-on to the YUI it can now extend Prototype and jQuery. Includes an impress interface.
  • Dojo is a small library focused on interpreter independence and small core size.
  • MochiKit - A framework that has focus on scripting language standards including ECMAScript and the W3C DOM.

Click here to read the full post on the frameworks.

Making the Most of Java 5.0: Enum Example

Tagged:  

"Hello World!" examples are great for general introductions to a concept, but often tend to lack much depth. So, as a follow-up to the original article on enums in Java 5.0, this article goes into a little more depth with a real-world example.

The Container Enum

Figure 1 below illustrates the enumeration of possible application servers to which an application can deploy. Why is this useful? Many organizations have more than one Java application server in different environments, and an EAR or WAR may need to be redeployed to different servers; or, you may be developing a common framework that will be used in different environments. It is often helpful in these situations to abstract many of the (static) variances between containers so that redeployment to a different environment can be done with a minimum of effort.

Figure 1: The Container enum.

public enum Container {
   WEBSPHERE, WEBLOGIC, JBOSS, NONE;
}

Now, let's say the application being designed requires an application-controlled JTA TransactionManager (if, for example, the standard way of doing XA transactions cannot be used). But how one is acquired varies pretty widely, depending on which environment the code is running. The variances here can be handled with an abstract method added to the enum, as in Figure 2.

Figure 2: The Container enum with factory methods.

public enum Container 
{
     WEBSPHERE() {
        private String[] factoryNames =
           {"com.ibm.ws.Transaction.TransactionManagerFactory",
            "com.ibm.ejs.jts.jta.TransactionManagerFactory",
            "com.ibm.ejs.jts.jta.JTSXA"};
        @Override
	public TransactionManager getTransactionManager() 
            throws Exception {
	     for (int i = 0; i < factoryNames.length; i++)  {
	         Method getTxMgr = null;
		 try {
		   //attempt to get class and method
		   Class<?> txMgrFactory = Class.forName(factoryNames[i]);
		   getTxMgr = txMgrFactory
                      .getMethod("getTransactionManager", null);	
		  } catch (Exception e) { 
		       continue;
		  }
		  //attempt to invoke method (let exception throw...)
                  return (TransactionManager) getTxMgr.invoke(null, null);
	     }
	     //if all else fails
	     return null;   //or throw exception
	}
     },

     WEBLOGIC() {
        @Override
	public TransactionManager getTransactionManager() 
          throws Exception {
           InitialContext ctx = null;
           try {
             ctx = new InitialContext();
             return (TransactionManager) ctx
               .lookup("java:comp/UserTransaction");
           } finally {
              if(ctx!=null) {
                 try { ctx.close(); } catch (NamingException e) {}
              }
           }
        }
     },

     JBOSS() {
      @Override
	public TransactionManager getTransactionManager() 
          throws Exception {
           InitialContext ctx = null;
           try {
             ctx = new InitialContext();
             return (TransactionManager) ctx
               .lookup("java:/TransactionManager");
           } finally {
              if(ctx!=null) {
                 try { ctx.close(); } catch (NamingException e) {}
              }
           }
        }
     },

    // Standalone environ or server w/o TM
    NONE() {
      @Override
	public TransactionManager getTransactionManager() 
          throws Exception {
	   //Use reflection to avoid necessary dependency
	   Class<?> clazz = Class.forName("org.objectweb.jotm.Jotm");
	   Constructor<?> constr = clazz.getConstructor(boolean.class, 
            boolean.class);
	   Object jotm = constr.newInstance(true, false);
	   Method getTxMgr = clazz.getMethod("getTransactionManager", 
            (Class[])null);
	   return TransactionManager.class.cast(getTxMgr
             .invoke(jotm, (Object[])null));
        }
    };

    // abstract method
    public abstract TransactionManager getTransactionManager() 
         throws Exception;
}

Here we are defining an abstract method getTransactionManager() as a factory method for getting or creating a JTA TransactionManager in a manner similar to the Spring Framework's JtaTransactionManager. Each enumeration instance must implement this method. In most cases, a JEE-compliant server will have a JNDI lookup that can be used. For WebSphere, there is no API for gettng a TransactionManager directly, but instead a time-honored backdoor for creating one. In the case of NONE (either a stand-alone environment or a server that has no TransactionManager), JOTM is used. Of course, the enum would be a lot shorter if the calls were delegated to factory classes, but that's an implementation detail.

Since the JMX default domain for most major Java application servers is self-describing, something like the following snippet of code can be used to "auto-sniff" the container environment:

     public Container lookupContainer() {
          String defaultDomain = ManagementFactory
              .getPlatformMBeanServer()
              .getDefaultDomain();
          try {
               return Container.valueOf(defaultDomain.toUpperCase());
          } catch (Exception e) { /*...assume none....*/ }
          return Container.NONE;   // or null if no default behavior
     }

After all of that, the client code to use it is a simple line:

lookupContainer().getTransactionManager():

Conclusion

The Container enum is a good illustration of the power of enumerations in Java compared to their C/C++ counterparts. By associating behavior with each enum instance, a smooth way of dispatching getTransactionManager() to the appropriate implementation has been created. This points out another fact: each enum instance (WEBSPHERE, WEBLOGIC, etc.) is implicitly a subclass of the enum class Container itself. This comes in handy since it means that many other object-oriented design patterns (Abstract Factory, Command, Visitor, and Strategy, to name a few) can be implemented using enums. Those, of course, are left as an exercise to the reader.

Voices That Matter: GWT - Conversation with Josh Bloch

Video of the "Conversation with Josh Bloch" from Pearson Education's Voices That Matter: Google Web Toolkit 2007 conference.

Josh Bloch is the Chief Java Architect at Google. Previously he was a Distinguished Engineer at Sun Microsystems and a Senior Systems Designer at Transarc. He led the design and implementation of numerous Java platform features, including the JDK 5.0 language enhancements and the Java Collections Framework. He holds a Ph.D. in Computer Science from Carnegie-Mellon University and a B.S. in Computer Science from Columbia University.

Check out more session videos and presentation slides from the conference.

The Closures Controversy in Java

Tagged:  

I just finished viewing Joshua Bloch's talk at JavaPolis 2007 entitled "The Closures Controversy", where he critiques one of the leading proposals for adding closures to the Java language (BGGA, named as an acronym after its authors). The presentation is eye-opening, and it is thought-provoking to see two of Java's biggest lumunaries on opposite sides of the debate. Of course, Bloch himself is one of the authors of an alternative proposal for adding closures, CICE (Concise Instance Creation Expressions).

It's not Clarence Darrow in the "Scopes Monkey Trial", but it's the closest we programmers can get. I won't go into huge detail about the two proposals except to say that BGGA adds full support for functional types whereas CICE is a more concise way of expressing anonymous inner classes in Java (there are many places on the web to go into the details). The heart of the debate really boils down to Defensive Programming VS. (for lack of a better term) "Let the programmer do whatever he/she wants (and let the language support it)". The former position being more conservative and more pragmatic, the later a more libertarian view that experts (programmers) are smart and should be allowed to do whatever they want. Ironically, these two opposites are also embodied in many ways in differing philosophies in design between Java and its antecedent language, C++. Java was, after all, "C++ --", the language that made smart decisions to remove features from C++ that were considered dangerously error-prone: pointers, explicit memory deallocation, etc.

So clearly Bloch is in the defensive programming camp whereas Neal Gafter, the main proponent of BGGA, is on the other side. And, I have to admit, I am on Bloch's side as well, for many reasons.

  • BGGA is complex. Non-local returns, continues, and breaks have a great potential to confuse the average programmer. The syntax, when viewed in even moderately complex code, looks cryptic. Even if you get past the syntax and non-local oddities you have to acknowledge, as Bloch so eloquently pointed out, that new features tend to add somewhere between quadratic and exponential complexity to a language because of their interaction with existing features. This was the *gotcha* with generics, and I have no desire to see that repeated with closures.
  • Defensive programming is at the very heart of what Java is as a language. And, by and large, it is this philosophy which has made it so successful. Trying to make it into an "experts language", as C++ is, cuts against the grain of the spirit of the language. (As an aside, it is telling to note that Gafter himself was a member of the C++ Standards Committee.)
  • The Java camp is already losing programmers to newer languages like Ruby because it is "too complex". Do we really want to add more complexity to drive away more programmers from the language? Simplicity is beauty, and (as someone once said) the most important decisions in a language have to do with what features you should leave out.
  • There are already other languages that target the JVM (and hence at least theoretically can interact with existing Java code) which handle closures in a much more natural way: JRuby, Groovy, Scala. Static typing without type inference tends to make control structures like closures much more challenging, if not downright awkward. Both Ruby and Groovy are dynamically typed and Scala uses static type inference. Perhaps one of these languages is a more suitable vehicle for those who feel they really need closures.

Whatever the result of the debate, it is likely that closures in some form will land in the Java language in the not-too-distant future. Right now, BGGA seems to have the momentum, which is unfortunate. Neal Gafter may, in a very well-intentioned way, be leading Java down a path of bloated complexity from which it will never recover; and which will ultimately result in Java yielding its leading position to a new language that is far more agile.

Java Tip of the Day: Using Interfaces

Tagged:  

Anyone who has ever programmed in Java is intimately familiar with using the interface, Java's purely abstract class and cleaner answer to C++'s concept of multiple inheritance. It's an old idea by now, and yet new ideas can somehow breathe life into old ones. And this is what has happened recently with interfaces.

The obvious use of interfaces is in abstracting behavior (i.e., methods) of objects and allowing implementing classes to implement this behavior. For example, take an interface for returning an SQL connection from different sources:

public interface ConnectionFactory() { 
     public Connection getConnection(); 
}

public class JndiConnectionFactory() { 
     public Connection getConnection()  { 
          // get DataSource from JNDI, return Connection 
     }
}

public class SingleConnectionFactory() {
     public Connection getConnection()  { 
          // create Connection using properties and return
     }
}

Here the ConnectionFactory interface is defined using two different implementations, one for container environments (JNDI) and the other when used in a non-container (stand-alone) environment (JDBC).

OK, this is old news. But there is another, more subtle, use of interfaces if you think about them as a replacement for multiple inheritance or as being somewhat akin to "aspects" in AOP: that interfaces are a way of layering behavior onto an object. Thought of this way, the style of defining monolithic interfaces with many methods becomes less desirable than defining many interfaces that define one or a few methods that describe a single aspect of an object's behavior.

Let me give two examples of this idea, one from the core language itself and the other my own.

First, the core language. When Java 5 was introduced, a few simple one-method common interfaces were also introduced. One of these was the java.lang.Iterable interface which defined the simple method public Iterator iterator(). Combined with the introduction of generics, this allowed the addition of a new "foreach" construct that looks like:

for(T obj : Iterable<T>) {
     //...logic here...
}

By isolating the simple behavior of returning an iterator, Java 5 was able to have any class that implements this be used in the new "foreach" loop (not just Collections). Joshua Bloch has also proposed an addition to Java 7 of having "resource blocks" where any object that implements a Closeable interface will be automatically closed at the end of the block.

The second example has to do with defining public and private APIs. What if, in the example above, I were using the ConnectionFactory in designing a framework that would be used as a library in other Java applications, and I wanted to define an internally used Connection that I did not want exposed to the client of the library? And that I also want to use the JndiConnectionFactory and SingleConnectionFactory implementations above with this internally-used Connection?

One approach might be to create two different ConnectionFactory objects, exposing one to the client and the other hidden internally to the framework. This is a perfectly reasonable approach, but let's say (for purposes of illustration) that this is cumbersome because of the framework design and you would rather have a single, centralized ConnectionFactory that defines another method, public Connection getInternalConnection(). This presents a problem because you really don't want to expose this private API method to the client (one of Java's limitations is that there aren't a lot of options for information hiding between classes: package private or protected).

A clever solution to this issue might be to define two separate interfaces, one that exposes a public API and the other that exposes a private API. This way you can have the various implementing classes implement both the public and private API, and you only hand out a reference to the public API to the client.

public interface InternalConnectionFactory {
     public Connection getInternalConnection();
}

public class JndiConnectionFactory 
     implements ConnectionFactory, InternalConnectionFactory { ... }

public class ConnectionFactoryWrapper implements ConnectionFactory {
     private ConnectionFactory wrappedFactory;
     public ConnectionFactoryWrapper(ConnectionFactory wrappedFactory) {
          this.wrappedFactory = wrappedFactory;
     }
     //delegate methods here
}

//etc...

// This class defines the way the client gets a connection factory...
public class AppContext {
     public ConnectionFactory getConnectionFactory() { 
          return new ConnectionFactoryWrapper(connFactoryImpl);
     }
}

The wrapper class here is used to protect the internal methods from being accessed by the client (could also use a dynamic proxy here). This promotes a cleaner, simpler public API without "polluting" it with methods meant to be only used internally by the framework.

OSGi and the upcoming Java Module System handle this need in a much more robust way, but using OSGi may not be practical for most programmers and use of JSR-277 may be very far away for most organizations which are just migrating to Java 5. Clever use of interfaces addresses this need in a simple and practical way.

Making the Most of Java 5: Generics

Tagged:  

In the first two articles of this series on Java 5, I explored enums and annotations, the no-brainer enhancements to Java that everyone should use. Now I am going to tackle the more challenging addition to the Java language, generics. In the aftermath of all the changes to the core language that took place in Java 5, generics has emerged as the most problematic, holding significant expressive power but carrying with it a lot of baggage. This baggage has come in the form of many compiler warnings, unexpected compiler errors, and other surprises. Yet, used correctly, generics are very powerful and can actually produce much cleaner code than was possible previously.

Introduction

The simplest explanation of generics is that they are variables to types (which are bound at compile-time). Quite often in object-oriented programming, there arises a need to represent a "generic" type reference, for which the actual type can be just about anything. A classic example of this are objects in java.util.List: a list can contain any type of object, and so its accessor methods often are represented by an Object return value. This led to the frequent need to cast the return value from these types of methods, a process prone to the dreaded ClassCastException. Generics get rid of the need to do unsafe casting--at the bytecode level, casting is still taking place, but it is guaranteed to be safe by the compiler.

Generics make code clearer. Take for example the following method signature: public List getThings(). What type is contained in the returned List? Without documentation, or code to test it, it would be difficult to tell. With a method like public List<String> getThings(), however, it is clear that the returned structure contains String objects.

Generics enforce type safety, since calling an add("Hello World!") on a List<Integer> produces a compile error. In non-generic code, this would not produce an error.

History

The origin of generics in Java came from an experimental language that extended Java, GJ (Generic Java). Inspired by templates in the C++ programming language, but with significant differences, GJ was the testing ground for the concepts that ultimately became the generics implementation in Java 5. The process of adding generics to Java was done as a Java Community Process (JCP) as the JSR-014 proposal.

How Generics Work

The key improvement in Java's implementation of generics (vs. C++ templates) is that Java generics are much more type safe, i.e. Java can enforce type relationships whereas C++ could not. This is because generic types in Java are actually compiled into the .class file rather than text-substituted by a pre-compiler. This means that Collection<A> is a different type than Collection<B>(at least at compile-time), and this difference is enforced by the compiler. But in a strange (and some would say cruel) twist of fate, this generic type information is erased at compile-time--a process referred to as type erasure--when the .java file is compiled (though generic information does seem to be kept in the class file metadata area). Type erasure was done to maintain backward compatibility with older Java code, and is the key source of controversy in the generics implementation, as it is the source of many of the problems and corner cases that generics add to the language. Allowing generic types to be kept at runtime (so-called reified generics) is one of the proposals on the table for Java 7.

The Syntax of Generics

Java allows both classes and methods to be genericized. The appropriate declarations are done using angled brackets containing a comma-separated list of type parameters, like <A,B,C> (by convention, generic variables are written as a single capitalized letter, but any valid variable name can be used). Generic declarations occur after the class name in a class declaration but before the return type in a method declaration. Here is an example using both:

public class Structure<T> {
     public T get() { ... }
     public <G> G getDifferent() { ... }
}

Generics can be nested, like Map<String,Collection<Object>>.

Generics can also include wildcards using the ? symbol. Why is this needed, since generic types are already variables? The answer is because generics are not covariant (unlike arrays). That is to say, Collection<Object> c = new ArrayList<String>() will not compile because c.add(new Integer(1)) is perfectly legal but obviously an Integer is not a String. The problem is solved with wildcards, since Collection<?> can be the supertype of any Collection.

Generics can specify a range of types (bounded wildcards or type variables), either subtypes

     List<? extends Node> or List<T extends Node>

or supertypes

     List<? super Element>

(Note: super can only be used with bounded wildcards.)

Type Tokens

Because of type erasure, it is impossible to (accurately) get the Class of a generic type at runtime. T.class will not compile and calling getClass() on a generic type returns Class<? extends Object>. But sometimes the Class is needed to correctly cast (the cast() method was added to Class in Java 5, and Class itself was genericized) or newInstance() an object of a generic type. This is where passing in the Class as a "type token" comes in. For example,

public <T> T createObject(Class<T> clazz) {
     return clazz.newInstance();
}

Here you are guaranteed that the return type will be of type T, whereas in J2SE 1.4 and earlier, this was not true. In order to illustrate this point let's look at the equivalent non-generic code:

public MyType createObject(Class clazz) {
     return (MyType) clazz.newInstance();
}

The cast here is not guaranteed to succeed. If the caller invoked this method using createObject(String.class), a ClassCastException would be raised.

Super Type Tokens

You cannot create type tokens for generic classes because of type erasure, i.e. List<String>.class will not compile. There is a "backdoor" solution to this problem because, actually, not all generic information is erased at runtime. The Class method called getGenericSuperclass() allows the differentiation between, say, between List<String> and List<Integer> at runtime using the "super type token" concept. It works like this:

public abstract class TypeReference<T> {
     private final Type type;
     protected TypeReference() {
          Type superclass = getClass().getGenericSuperclass();
          this.type = ((ParameterizedType) superclass)
             .getActualTypeArguments()[0];
     }
     // equals() and hashCode() base on Type
}

A "super type token" would be created using an empty subclass of TypeReference, like

new TypeReference<List<String>>() {}

This would be differentiable from a TypeReference<List<Integer>> at runtime. For a more thorough implementation, see the TypeLiteral class from Google Guice.

Annoyances

There are many corner cases and *gotchas* in generics. Here are a few of my favorites.

  • Generics can make your code very verbose. The classic example of this is the declaration and initialization of a Map:
    Map<String,Collection<Number>> map =
        = new HashMap<String,Collection<Number>>();
  • Too many generic declarations and/or overuse of bounded types can make code difficult to read.
  • The static getClass() method on any Java object returns a Class<? extends $type>, not Class<$type> (where $type is the type on which the method is called). This means, for example, the code Class<String> c = "Hello World!".getClass() does not compile because Class<? extends String> is not assignable to Class<String>. This tends to force you into using type tokens, often having to add Class<T> to method signatures where you would not have done so otherwise.
  • Wildcards and type variables don't mix. The generic type Collection<? extends Number> is not the same as Collection<T extends Number>, so you must be careful in how use the two, especially in method signatures.
  • Arrays and generics don't mix. The general advice here is to use generic Collections rather than arrays.
  • Sometimes, because of generics, you will have to do an unsafe cast from one generic type to another. It will happen.
  • @SuppressWarnings is, if not your best friend, at least a close companion (but try to use it only if you can prove that what you are doing is safe).

Conclusion

Generics are a powerful and, by and large, welcome feature in Java 5. Using them does improve your code. But type erasure opens up a big hole in the Java type system that is created between the bytecode compiler and the runtime compiler. This could be solved by the reification of generics, but reification breaks backward compatibility with Java classes written against pre-Java 5 compilers. A suggested solution has been to introduce optionally reified generics (using something like List<@String> syntax), but I think that having two different types of generics may traumatize the Java type system (and Java programmers) even further. A better decision might be to simply break backward compatibility at some point and let programmers decide if they need reification enough to forgo compatibility.

Links

The Generics Tutorial, Gilad Bracha.
Effective Java Reloaded (JavaOne), Joshua Bloch.
Super Type Tokens, Neal Gafter
Limitations of Super Type Tokens, Neal Gafter
Java Generics FAQ, Angelika Langer.

Syndicate content