how to declare Class.class with valid generics

孤者浪人 提交于 2019-12-03 21:04:19

问题


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


回答1:


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




回答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.




回答3:


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!


来源:https://stackoverflow.com/questions/6065998/how-to-declare-class-class-with-valid-generics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!