基于java文档:
在类型擦除过程中,Java编译器会擦除所有类型 参数并用类型的第一个边界替换每个参数 参数是有界的,如果类型参数是无界的,则为Object。
现在,事情就是这样的一个类:
public class MyCreator<T> {
Class<T> kind;
MyCreator(Class<T> kind) {
this.kind = kind;
}
void printInstanceClass() throws Exception{
System.out.println(kind.newInstance().getClass());
}
public static void main(String[] args) throws Exception{
MyCreator<String> myCreator = new MyCreator<String>(String.class);
myCreator.printInstanceClass();
}
}
printInstanceClass()
方法实际打印“class java.lang.String”。
如果编译器正在使用Object替换类内部的T,我想也会删除与kind
关联的类的信息并替换为Class。那么,newInstance()
方法如何返回String实例而不是Object 1?
答案 0 :(得分:2)
你传递了String.class(它没有被删除,但是在运行时保留了一个具体的类),然后在该类上调用newInstance,这会产生一个String。
输出检查具体对象(String)并显示其类。
答案 1 :(得分:2)
棘手的部分是String.class
参数。它不是类型参数,而是一个普通的旧参数,如String[] args
。因此,Class<T> kind
将为String.class
,因此printInstanceClass()
可以在运行时访问它。
这是一种常见做法,也在Effective Java中提出。
因此,在类型擦除之后,此代码在逻辑上等同于此代码:
public class MyCreator {
Class kind; // this will be String.class at runtime
MyCreator(Class kind) {
this.kind = kind;
}
void printInstanceClass() throws Exception{
System.out.println(kind.newInstance().getClass());
}
public static void main(String[] args) throws Exception{
MyCreator myCreator = new MyCreator(String.class);
myCreator.printInstanceClass();
}
}
答案 2 :(得分:1)
有关作为myCreator
对象的通用参数传递的类(类型)的信息将被删除,但不会存储kind
对象中存储的信息。
使用Class<?>
对象方法很好,但如果您尝试从通用T
类型获取类信息,则会遇到编译错误,例如:
void printInstanceClass() throws Exception{
System.out.println(T.class.newInstance().getClass()); // error!
}
虽然这并不容易,但也存在执行上述操作的解决方法。