299

There's a good discussion of Generics and what they really do behind the scenes over at this question, so we all know that Vector<int[]> is a vector of integer arrays, and HashTable<String, Person> is a table of whose keys are strings and values Persons. However, what stumps me is the usage of Class<>.

The java class Class is supposed to also take a template name, (or so I'm being told by the yellow underline in eclipse). I don't understand what I should put in there. The whole point of the Class object is when you don't fully have the information about an object, for reflection and such. Why does it make me specify which class the Class object will hold? I clearly don't know, or I wouldn't be using the Class object, I would use the specific one.

Community
  • 1
  • 1
Karl
  • 8,967
  • 5
  • 29
  • 31

11 Answers11

239

All we know is "All instances of a any class shares the same java.lang.Class object of that type of class"

e.g)

Student a = new Student();
Student b = new Student();

Then a.getClass() == b.getClass() is true.

Now assume

Teacher t = new Teacher();

without generics the below is possible.

Class studentClassRef = t.getClass();

But this is wrong now ..?

e.g) public void printStudentClassInfo(Class studentClassRef) {} can be called with Teacher.class

This can be avoided using generics.

Class<Student> studentClassRef = t.getClass(); //Compilation error.

Now what is T ?? 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. Later that T will be substituted with
valid Class name during initialization (HashMap<String> map = new HashMap<String>();)

e.g) class name<T1, T2, ..., Tn>

So Class<T> represents a class object of specific class type 'T'.

Assume that your class methods has to work with unknown type parameters like below

/**
 * Generic version of the Car class.
 * @param <T> the type of the value
 */
public class Car<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

Here T can be used as String type as CarName

OR T can be used as Integer type as modelNumber,

OR T can be used as Object type as valid car instance.

Now here the above is the simple POJO which can be used differently at runtime.
Collections e.g) List, Set, Hashmap are best examples which will work with different objects as per the declaration of T, but once we declared T as String
e.g) HashMap<String> map = new HashMap<String>(); Then it will only accept String Class instance objects.

Generic Methods

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

The syntax for a generic method includes a type parameter, inside angle brackets, and appears before the method's return type. For generic methods, the type parameter section must appear before the method's return type.

 class Util {
    // Generic static method
    public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

 class Pair<K, V> {

    private K key;
    private V value;
}

Here <K, V, Z, Y> is the declaration of types used in the method arguments which should before the return type which is boolean here.

In the below; type declaration <T> is not required at method level, since it is already declared at class level.

class MyClass<T> {
   private  T myMethod(T a){
       return  a;
   }
}

But below is wrong as class-level type parameters K, V, Z, and Y cannot be used in a static context (static method here).

class Util <K, V, Z, Y>{
    // Generic static method
    public static  boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

OTHER VALID SCENARIOS ARE

class MyClass<T> {

        //Type declaration <T> already done at class level
        private  T myMethod(T a){
            return  a;
        }

        //<T> is overriding the T declared at Class level;
        //So There is no ClassCastException though a is not the type of T declared at MyClass<T>. 
        private <T> T myMethod1(Object a){
                return (T) a;
        }

        //Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).  
        private T myMethod1(Object a){
                return (T) a;
        }       

        // No ClassCastException        
        // MyClass<String> obj= new MyClass<String>();
        // obj.myMethod2(Integer.valueOf("1"));
        // Since type T is redefined at this method level.
        private <T> T myMethod2(T a){
            return  a;
        }

        // No ClassCastException for the below
        // MyClass<String> o= new MyClass<String>();
        // o.myMethod3(Integer.valueOf("1").getClass())
        // Since <T> is undefined within this method; 
        // And MyClass<T> don't have impact here
        private <T> T myMethod3(Class a){
            return (T) a;
        }

        // ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
        // Should be o.myMethod3(String.valueOf("1").getClass())
    private  T myMethod3(Class a){
        return (T) a;
    }


        // Class<T> a :: a is Class object of type T
        //<T> is overriding of class level type declaration; 
        private <T> Class<T> myMethod4(Class<T> a){
            return  a;
        }
    }

And finally Static method always needs explicit <T> declaration; It wont derive from class level Class<T>. This is because of Class level T is bound with instance.

Also read Restrictions on Generics

Wildcards and Subtyping

type argument for a generic method

Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101
  • 2
    My answer on bounded wildCards http://stackoverflow.com/questions/1368166/what-is-a-difference-between-super-e-and-extends-e/15252219#15252219 – Kanagavelu Sugumar Oct 23 '13 at 18:25
  • " Class represents a class object of specific class type 'T'. " that does makes sense. Thank you.. – codezoner May 25 '15 at 10:39
  • 2
    This answer is terribly confusing in the way it uses Classes (from school) in a question about Classes (in Java). It's hard to know what the author is talking about from a sentence to another. – Echox Feb 13 '19 at 15:11
  • @Echox I am sorry, I can improve it, if you have any specific questions. – Kanagavelu Sugumar Feb 14 '19 at 08:17
  • 1
    https://stackoverflow.com/questions/4829631/unusual-generic-syntax-arrays-stringaslist – Kanagavelu Sugumar Jul 26 '19 at 16:32
  • @Echox Maybe it was the naming scheme? Anyone else notice the irony in using types Teacher and Student to explain class references? LMAO – Nate T Jul 23 '20 at 00:06
159

Using the generified version of class Class allows you, among other things, to write things like

Class<? extends Collection> someCollectionClass = someMethod();

and then you can be sure that the Class object you receive extends Collection, and an instance of this class will be (at least) a Collection.

Aryaveer
  • 943
  • 1
  • 12
  • 27
Yuval
  • 7,987
  • 12
  • 40
  • 54
40

From the Java Documentation:

[...] More surprisingly, class Class has been generified. Class literals now function as type tokens, providing both run-time and compile-time type information. This enables a style of static factories exemplified by the getAnnotation method in the new AnnotatedElement interface:

<T extends Annotation> T getAnnotation(Class<T> annotationType); 

This is a generic method. It infers the value of its type parameter T from its argument, and returns an appropriate instance of T, as illustrated by the following snippet:

Author a = Othello.class.getAnnotation(Author.class);

Prior to generics, you would have had to cast the result to Author. Also you would have had no way to make the compiler check that the actual parameter represented a subclass of Annotation. [...]

Well, I never had to use this kind of stuff. Anyone?

Peter Ajtai
  • 56,972
  • 13
  • 121
  • 140
raupach
  • 3,092
  • 22
  • 30
  • 2
    I (thought I) did. A framework (of sorts) I worked with required you to pass the classname of services your module depended on. I built a layer on top of that that took Class objects, as to restrict the amount of choices. Using the `Class extends X>` notation I figured I could limit it to 'service' types only. Except there was no common 'service' type, so I could only do it with `Class>`. Alas. – cthulhu Jan 18 '11 at 11:36
11

I have found class<T> useful when I create service registry lookups. E.g.

<T> T getService(Class<T> serviceClass)
{
    ...
}
Kire Haglin
  • 6,569
  • 22
  • 27
6

Following on @Kire Haglin's answer, a further example of generics methods can be seen in the documentation for JAXB unmarshalling:

public <T> T unmarshal( Class<T> docClass, InputStream inputStream )
         throws JAXBException {
  String packageName = docClass.getPackage().getName();
  JAXBContext jc = JAXBContext.newInstance( packageName );
  Unmarshaller u = jc.createUnmarshaller();
  JAXBElement<T> doc = (JAXBElement<T>)u.unmarshal( inputStream );
  return doc.getValue();
}

This allows unmarshal to return a document of an arbitrary JAXB content tree type.

Stew
  • 4,495
  • 6
  • 31
  • 41
6

As other answers point out, there are many and good reasons why this class was made generic. However there are plenty of times that you don't have any way of knowing the generic type to use with Class<T>. In these cases, you can simply ignore the yellow eclipse warnings or you can use Class<?> ... That's how I do it ;)

bruno conde
  • 47,767
  • 15
  • 98
  • 117
  • 1
    `@SuppressWarnings("unchecked")` comes to the rescue! (Just be careful to always apply it to as small a scope as possible as it *does* obscure potential problems in your code.) – Donal Fellows Jan 18 '11 at 10:46
5

In java <T> means Generic class. A Generic Class is a class which can work on any type of data type or in other words we can say it is data type independent.

public class Shape<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

Where T means type. Now when you create instance of this Shape class you will need to tell the compiler for what data type this will be working on.

Example:

Shape<Integer> s1 = new Shape();
Shape<String> s2 = new Shape();

Integer is a type and String is also a type.

<T> specifically stands for generic type. According to Java Docs - A generic type is a generic class or interface that is parameterized over types.

Priyesh Diukar
  • 2,032
  • 1
  • 15
  • 19
3

You often want to use wildcards with Class. For instance, Class<? extends JComponent>, would allow you to specify that the class is some subclass of JComponent. If you've retrieved the Class instance from Class.forName, then you can use Class.asSubclass to do the cast before attempting to, say, construct an instance.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0

Just to throw in another example, the generic version of Class (Class<T>) allows one to write generic functions such as the one below.

public static <T extends Enum<T>>Optional<T> optionalFromString(
        @NotNull Class<T> clazz,
        String name
) {
    return Optional<T> opt = Optional.ofNullable(name)
            .map(String::trim)
            .filter(StringUtils::isNotBlank)
            .map(String::toUpperCase)
            .flatMap(n -> {
                try {
                    return Optional.of(Enum.valueOf(clazz, n));
                } catch (Exception e) {
                    return Optional.empty();
                }
            });
}
zeronone
  • 2,912
  • 25
  • 28
-1

It is confusing in the beginning. But it helps in the situations below :

class SomeAction implements Action {
}

// Later in the code.
Class<Action> actionClass = Class.forName("SomeAction"); 
Action action = actionClass.newInstance();
// Notice you get an Action instance, there was no need to cast.
fastcodejava
  • 39,895
  • 28
  • 133
  • 186
  • 4
    Isn't that just an incredibly complicated way of saying Action a = new Action() ? – Karl Feb 02 '10 at 19:17
  • 1
    `Action a = new Action() `? `Action` i an interface, it is `SomeAction` we are trying get an instance of. We only have the name of `SomeAction` available at runtime. – fastcodejava Feb 02 '10 at 22:23
  • This does not pass typechecking: the java compiler has no way to tell that Class.forName("SomeAction") will be of type Class, since this will only be known at runtime. – tonio Nov 23 '10 at 17:59
  • @tonio, right, so you probably have to wrap that first line in some kind of try/catch. But assuming no exception is thrown there, the second line is guaranteed to work. – Tyler Jun 18 '11 at 03:28
  • @MatrixFrog, not really: at runtime, the cast to `Class` is equivalent to a cast to `Class`. This will add implicit casts to `Action` when you use the instance, but there is no static guarantee the casts will not fail. This will only work is `SomeAction` is a subclass of `Action`, and at compile time, java has not way to tell that. – tonio Jun 18 '11 at 06:30
  • @tonio I think we're saying more or less the same thing. I said you'd have to wrap the first line in a try/catch, but (without trying it since I don't have my IDE open) I think it would actually have to look like `Class actionClass = (Class) Class.forName("SomeAction");` and you're right that the cast could fail. My main point was that the second line will always succeed, no matter where it's called (unless `actionClass` is null) because the compiler won't allow `actionClass` to contain a class that doesn't implement `Action`. – Tyler Jun 18 '11 at 06:39
  • Class does not inherit from Class. That's just a mistake, and the cast, while legal, is mostly due to the fact that generics are somewhat of an afterthought, and therefore need to allow such casts. Yes, you can use some functions after this cast and get what you might expect, but others might lead to confusion. It is not true that if X extends Y then Class extends Class. – Thomas Andrews Feb 22 '12 at 14:18
  • 2
    What you are really describing is that SomeAction.class matches the pattern Class extends Action> - that is, if you have a method useAction(Class extends Action> klass), you can call useAction(SomeAction.class). – Thomas Andrews Feb 22 '12 at 14:30
-4

Just use the beef class:

public <T> T beefmarshal( Class<beef> beefClass, InputBeef inputBeef )
     throws JAXBException {
     String packageName = docClass.getPackage().getBeef();
     JAXBContext beef = JAXBContext.newInstance( packageName );
     Unmarshaller u = beef.createBeef();
     JAXBElement<T> doc = (JAXBElement<T>)u.beefmarshal( inputBeef );
     return doc.getBeef();
}
MasterAM
  • 16,283
  • 6
  • 45
  • 66
yaa
  • 11
  • 4
    This doesn't really provide a full answer to the question. If you think you have something to add, edit this answer. – MasterAM Jul 29 '13 at 19:17