What does the generic nature of the class Class<T> mean? What is T?

29,565

Solution 1

Type parameter <T> has been added to java.lang.Class to enable one specific idiom1 - use of Class objects as type-safe object factories. Essentially, the addition of <T> lets you instantiate classes in a type-safe manner, like this:

T instance = myClass.newInstance();

Type parameter <T> represents the class itself, enabling you to avoid unpleasant effects of type erasure by storing Class<T> in a generic class or passing it in as a parameter to a generic method. Note that T by itself would not be sufficient to complete this task2: the type of T is erased, so it becomes java.lang.Object under the hood.

Here is a classic example where <T> parameter of the class becomes important. In the example below, Java compiler is able to ensure type safety, letting you produce a typed collection from a SQL string and an instance of Class<T>. Note that the class is used as a factory, and that its type safety can be verified at compile time:

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;
}

Since Java erases the type parameter, making it a java.lang.Object or a class specified as the generic's upper bound, it is important to have access to the Class<T> object inside the select method. Since newInstance returns an object of type <T>, the compiler can perform type checking, eliminating a cast.


1 SUN Oracle has published a good article explaining all this.
2 This is different from implementations of generics without type erasure, such as one in .NET.
3 Java Generics tutorial by Oracle.

Solution 2

The answer by dasblinkenlight already demonstrated one of the main uses of this parameter. There is one more aspect I consider relevant: using that parameter, you can restrict the kind of class you want to pass at a given location. So e.g.

Class<? extends Number> cls

means that cls may be any class implementing the Number interface. This can help catching certain errors at compile time, and makes class argument requirements more explicit.

Perhaps a comparison to the case without generics is in order

// Java ≥5 with generics    // Java <5 style without generics
Class<? extends Foo> c;     Class c;
Foo t1 = c.newInstance();   Foo t1 = (Foo)c.newInstance();
Object obj;                 Object obj;
Foo t2 = c.cast(obj);       Foo t2 = (Foo)c.cast(obj);

As you can see, not having T as an argument would require a number of explicit casts, as the corresponding methods would have to return Object instead of T. If Foo itself is a generic type argument, then all those casts would be unchecked, resulting in a sequence of compiler warnings. You can suppress them, but the core issue remains: the compiler cannot check the validity of these casts unless you properly use the type argument.

Solution 3

In Java there's a single metaclass: Class. Its instances (only one per type exists) are used to represent classes and interfaces, therefore the T in Class<T> refers to the type of the class or interface that the current instance of Class represents.

Share:
29,565
Tim
Author by

Tim

Updated on July 09, 2022

Comments

  • Tim
    Tim almost 2 years

    I understand generics when it comes to collections. But what does it mean in the case of the Class<T> class? When you instantiate a Class object, there's only one object. So why the T parameter? What is it specifying? And why is it necessary (if it is)?