There is a parameter Class t in TestClass. t can not be assigned to ClassA.class?
puclic class TestClass<T extends ClassA>{
private Class<T> t;
public TestClass(Class<T> t){
//this.t = ClassA.class; // why not?
this.t = t;
}
}
but,Can be imported from outside。
public class Test{
public static void main(String[] args) {
TestClass tc = new TestClass(ClassA.class);//It's ok
}
}
I hope it can also be assigned internally!
CodePudding user response:
The generics on j.l.Class
are used solely so that the expression thatClass.newInstance()
has type T
, e.g. that you can do:
Class<String> c = ...;
String x = c.newInstance();
If you know that, and you think it through, your human brain, with all that contextual knowledge of what it is used for, realizes that this:
Class<Child> childClass = ...;
Class<Parent> parentClass = childClass;
is completely safe.
But javac cannot draw this conclusion. Javac is not going to be a walking dictionary of the uses of generics for each and every class that uses it. It just knows that generics generally would be unsafe if you allow this; it simply doesn't know that the unsafe situations do not occur for any usages of j.l.Class.
It occurs with lists, quite easily. here:
List<Integer> ints = new ArrayList<Integer>();
List<Number> nums = ints;
Number n = 5.0; // a double
assert n instanceof Double; // true, of course.
nums.add(n); // legal java, of course.
Integer i = ints.get(0); // um.. wait. uhoh.
Think long and hard about the above snippet. Write it in java code and try to compile it. It is the key to understanding the fundamental tenet that generics are invariant - a subtype is NOT assignable to the supertype, not when the types we are looking at are inside the <>
. You can replace: List<Number>
with List<? extends Number>
and then compilation gets further, but now .add()
fails (and in fact, you can't add anything to a List<? extends Whatever>
, except literally null
.