在泛型中键入Erasure

时间:2012-09-09 18:36:37

标签: java generics type-erasure

以下代码在类型擦除后查看运行时:

public class Test<T> {

T lst;
List<T> list1;
void meth() throws InstantiationException, IllegalAccessException{  T res = (T)lst.getClass().newInstance();}

static <S> void meth(S t){}
}  
class TestUse{
public static void main(String[] args) {
Test<Integer> gint = new Test<Integer>();
Test<String> gstr = new Test<String>();
gint.meth();
gstr.meth();

}   

3 个答案:

答案 0 :(得分:1)

以下代码不起作用:

T res = (T)lst.getClass().newInstance();

由于在所有可能的情况下,T在运行时都是Object类型。

一种解决方法是使用带有继承的泛型:

public abstract class Generic<T> {

    public abstract Class<T> getConcreteClass();

    public void doSomething() {
        Class<T> clazz = getConcreteClass();
        T t = clazz.newInstance();
        doSomethingWithT();
    }
}

public class ConcreteClass extends Generic<YourObject> {
    public Class<YourObject> getConcreteClass() {
        return YourObject.class;
    }
}

答案 1 :(得分:0)

假设您的Genrics类实际上是您的Test类,它应该等同于:

public class Genrics {

    Object lst;
    List list1;
    void meth() throws InstantiationException, IllegalAccessException {
        Object res = lst.getClass().newInstance();
    }

    static void meth(Object t){}
}  
class TestUse{
    public static void main(String[] args) {
        Genrics gint = new Genrics();
        Genrics gstr = new Genrics();
        gint.meth();
        gstr.meth();
}

无论我的假设是对还是错,考虑这一点的方法是,所有泛型类型参数都只是从代码中删除,并替换为类型参数的最具体边界(在您的情况下为Object)或在适当的地方没有。在需要的地方引入演员表。

Java Language Specification中详细列出了类型擦除的工作原理。

答案 2 :(得分:0)

我觉得它看起来像这样

public class Test {

    Object lst;
    List list1;
    void meth() throws InstantiationException, IllegalAccessException{  
        Object res =lst.getCla ss().newInstance();
    }

   static void meth(Object t){
   }
}

class TestUse{
    public static void main(String[] args) {
        Genrics gint = new Genrics();
        Genrics gstr = new Genrics();
        gint.meth();
        gstr.meth();
    }   

虽然我认为这不会按原样编译。没有Genrics类 - 或者是Test类。