how to declare Class.class with valid generics
Asked Answered
P

3

4

Note: purely out of curiosity and not for any actual use case.

I'm wondering if there is a way to declare the Class Class object with valid type parameters:

Class cc1 = Class.class; //raw type
Class<Class> cc2 = Class.class; //now parameter is raw type
Class<Class<?>> cc3 = Class.class; //compile error: inconvertible types

If Class and Class<?> are interchangeable, why are Class<Class> and Class<Class<?>> not?

EDIT: the question can be generalized to an issue of nested raw type parameters. For example:

ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList>(); //same compile error

EDIT2: I should rephrase the question a little: I know that

Class<?> c = Class.class;

is valid but I'm wondering why Class<Class> is not the same as Class<Class<?>>

Polytrophic answered 19/5, 2011 at 23:33 Comment(0)
M
2

Generics have some pretty serious limitations. In this case you can't assign a type to the inner type of Class<Class> because you're actually referencing the raw type, not an implementation of the raw type. It will give you a warning, but you have no way to fix that warning.

Class<Class<?>> by itself isn't an inconvertible type, you just can't assign a class directly to it because it doesn't have the type Class<Class<T>>, it has the type Class<T>.

Think of it another way; try List<List<String>>. To create that, you need to create a List that takes a List of Strings. This works because lists can contain lists.

A Class is more like a primitive than a data object, so I don't think it'd be possible to create a Class that is of type Class of something else.

Edit: your extra question about ArrayList<ArrayList<?>> is a more obvious example of the inconvertible type issue you're having with Class<Class<?>>.

Mylander answered 20/5, 2011 at 0:9 Comment(1)
The above answers gave detailed explanations of generics/wildcards, but this one got closest to what I was asking, which is why Class<Class> is not the same as Class<Class<?>>. Thanks to allPolytrophic
R
2

It's kind of difficult to see exactly what you're asking (or what you're trying to do).. but you can parametrize without raw types.

Class<? extends Object> cc4 = Class.class; // no raw types
Class<?> cc5 = Class.class; // also an option

As far as your last example is concerned, it makes no sense because it appears you want to make an array list of array lists that hold ?, but your declaration isn't declaring an array list of array lists that hold ?.

Properly written (but still not proper Java) would be:

ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<Integer>>(); // Type mismatch

Which is expected. It doesn't work for the same reason something like the following doesn't work:

Object o = new Object();
Integer i = new Integer(3);

o = i;
i.floatValue();
o.floatValue(); // can't access that method, we need to specifically cast it to Integer

Java types aren't proactively inferred (even in an inheritance chain).

If you want to keep the wildcard in there, you're welcome to, though:

ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<?>>(); // works!
Rodriquez answered 20/5, 2011 at 0:2 Comment(1)
Perfect answer. But I need to point out that <? extends Object> is exactly the same thing as <?>, that is the only reason the expression matches.Circumscription
C
2

The rule here is that the generic type in the left side must match the generic type in the right side.

Class<?> means a class of any type.

Class<?> c = Class.class; 

Works because Class of any type can be Class<Class>.

Class<Class<?>> cc3 = Class.class;

Do not work because Class.class type is Class<Class> which is not of type Class<Class<?>>

ArrayList<ArrayList<Integer>> lst = new ArrayList<ArrayList<Integer>>();
ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList<?>>();

Works because the two expressions match.

ArrayList<ArrayList<?>> lst = new ArrayList<ArrayList>();

Don't match.

Circumscription answered 20/5, 2011 at 0:4 Comment(0)
M
2

Generics have some pretty serious limitations. In this case you can't assign a type to the inner type of Class<Class> because you're actually referencing the raw type, not an implementation of the raw type. It will give you a warning, but you have no way to fix that warning.

Class<Class<?>> by itself isn't an inconvertible type, you just can't assign a class directly to it because it doesn't have the type Class<Class<T>>, it has the type Class<T>.

Think of it another way; try List<List<String>>. To create that, you need to create a List that takes a List of Strings. This works because lists can contain lists.

A Class is more like a primitive than a data object, so I don't think it'd be possible to create a Class that is of type Class of something else.

Edit: your extra question about ArrayList<ArrayList<?>> is a more obvious example of the inconvertible type issue you're having with Class<Class<?>>.

Mylander answered 20/5, 2011 at 0:9 Comment(1)
The above answers gave detailed explanations of generics/wildcards, but this one got closest to what I was asking, which is why Class<Class> is not the same as Class<Class<?>>. Thanks to allPolytrophic

© 2022 - 2024 — McMap. All rights reserved.