Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)?

like image 477
Tim Avatar asked Feb 23 '12 01:02

Tim


People also ask

What does T stand for in generics?

< T > is a conventional letter that stands for "Type", and it refers to the concept of Generics in Java. You can use any letter, but you'll see that 'T' is widely preferred. WHAT DOES GENERIC MEAN? Generic is a way to parameterize a class, method, or interface.

What is class T type in Java?

T is type parameters (also called type variables); delimited by angle brackets (<>), follows the class name. T is just a symbol, like a variable name (can be any name) declared during writing of the class file.

What is the meaning of generic class?

Generic classes encapsulate operations that are not specific to a particular data type. The most common use for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on.

What is the meaning in Java for \t?

What does \t mean in Java? This means to insert a new tab at this specific point in the text. In the below example, "\t" is used inside the println statement. It is similar to pressing the tab on our keyboard.


2 Answers

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.


1SUN 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.
3Java Generics tutorial by Oracle.
like image 79
Sergey Kalinichenko Avatar answered Oct 03 '22 22:10

Sergey Kalinichenko


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.

like image 41
MvG Avatar answered Oct 03 '22 22:10

MvG