1

基于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”。

如果编译器将类中的 T 替换为 Object,我猜想与 Class 关联的信息也会kind被删除并替换为 Class。那么,该方法如何newInstance()返回一个 String 实例而不是一个 Object 实例呢?

4

3 回答 3

2

您传递 String.class(它不会被删除,而是在运行时保留的具体类),然后在该类上调用 newInstance,这会产生一个字符串。

输出检查具体对象(字符串)并显示其类。

于 2016-06-24T13:01:56.573 回答
2

棘手的部分是String.class 参数。它不是类型参数,而是普通的旧参数,例如String[] args. 因此,Class<T> kindString.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();
    } 
}
于 2016-06-24T13:05:21.000 回答
1

作为对象的通用参数传递的有关类(类型)的myCreator信息将被删除,但不会删除存储在kind对象内部的信息。

使用Class<?>对象方法很好,但是如果您尝试从泛型T类型获取类信息,您会遇到编译错误,例如:

void printInstanceClass() throws Exception{ 
    System.out.println(T.class.newInstance().getClass()); // error!
}

尽管这并不容易,但也存在执行上述操作的解决方法。

于 2016-06-24T13:05:55.947 回答