Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
One of the changes in JDK 5.0 is that the classjava.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 parameterT
, you might well ask, what doesT
stand for? It stands for the type that theClass
object is representing.For example, the type of
String.class
isClass<String>
, and the type ofSerializable.class
isClass<Serializable>
. This can be used to improve the type safety of your reflection code.In particular, since the
newInstance()
method inClass
now returns aT
, 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:
You can call this either asinterface 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; }or you can declare a classselect(new Factory<EmpInfo>(){ public EmpInfo make() { return new EmpInfo(); }} , "selection string");EmpInfoFactory
to support theFactory
interfaceand call itclass EmpInfoFactory implements Factory<EmpInfo> { ... public EmpInfo make() { return new EmpInfo();} }The downside of this solution is that it requires either:select(getMyEmpInfoFactory(), "selection string");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:
- 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.
However, this would not give us a collection of the precise type we desire. Now thatCollection 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; }Class
is generic, we can instead write the following:The above code gives us the precise type of collection in a type safe way.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; }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.
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.