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
« Previous • Trail • Next »
Class Literals as Runtime-Type Tokens

> One of the changes in JDK 5.0 is that the class `java.lang.Class` is generic. It's an interesting example of using genericity for something other than a container class.

> Now that `Class` has a type parameter `T`, you might well ask, what does `T` stand for? It stands for the type that the `Class` object is representing.

> For example, the type of `String.class` is `Class<String>`, and the type of `Serializable.class` is `Class<Serializable>`. This can be used to improve the type safety of your reflection code.

> In particular, since the `newInstance()` method in `Class` now returns a `T`, you can get more precise types when creating objects reflectively.

> For example, suppose you need to write a utility method that performs a database query, given as a string of SQL, and returns a collection of objects in the database that match that query.

> One way is to pass in a factory object explicitly, writing code like:

> >     interface Factory<T> { T make();}

> >     public <T> Collection<T> select(Factory<T> factory, String statement) {
> >         Collection<T> result = new ArrayList<T>();
> >         /* Run sql query using jdbc */
> >         for (/* Iterate over jdbc results. */) {
> >             T item = factory.make();
> >             /* Use reflection and set all of item's fields from sql results. */
> >             result.add(item);
> >         }
> >         return result;
> >     }

> You can call this either as

> >     select(new Factory<EmpInfo>(){ public EmpInfo make() {
> >                                    return new EmpInfo();
> >                                    }}
> >           , "selection string");

> or you can declare a class `EmpInfoFactory` to support the `Factory` interface

> >     class EmpInfoFactory implements Factory<EmpInfo> {
> >         ...
> >         public EmpInfo make() { return new EmpInfo();}
> >     }

> and call it

> >     select(getMyEmpInfoFactory(), "selection string");

> The downside of this solution is that it requires either:
> - the use of verbose anonymous factory classes at the call site, or
> - declaring a factory class for every type used and passing a factory instance at the call site, which is somewhat unnatural.
> It is natural to use the class literal as a factory object, which can then be used by reflection. Today (without generics) the code might be written:

> >     Collection emps = sqlUtility.select(EmpInfo.class, "select * from emps");
> >     ...
> >     public static Collection select(Class c, String sqlStatement) {
> >         Collection result = new ArrayList();
> >         /* Run sql query using jdbc. */
> >         for (/* Iterate over jdbc results. */ ) {
> >             Object item = c.newInstance();
> >             /* Use reflection and set all of item's fields from sql results. */
> >             result.add(item);
> >         }
> >         return result;
> >     }

> However, this would not give us a collection of the precise type we desire. Now that `Class` is generic, we can instead write the following:

> >     Collection<EmpInfo> emps =
> >                           sqlUtility.select(EmpInfo.class, "select * from emps");
> >     ...
> >     public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
> >         Collection<T> result = new ArrayList<T>();
> >         /* Run sql query using jdbc. */
> >         for (/* Iterate over jdbc results. */ ) {
> >             T item = c.newInstance();
> >             /* Use reflection and set all of item's fields from sql results. */
> >             result.add(item);
> >         }
> >         return result;
> >     }

> The above code gives us the precise type of collection in a type safe way.

> This technique of using class literals as run time type tokens is a very useful trick to know. It's an idiom that's used extensively in the new APIs for manipulating annotations, for example.

« Previous • Trail • Next »
Previous page: The Fine Print
Next page: More Fun with Wildcards