Java 父类的类型擦除

Java 父类的类型擦除,java,generics,Java,Generics,我把一个类声明为 class Heap extends ArrayList<Element> 对于这些变量,父变量的泛型类型将被删除,并简单地表示为ArrayList。为什么会发生这种情况?这是在没有类型参数的情况下编写的泛型的行为。您至少应该将遗留代码转换成类似堆的东西 关于这方面的更多细节,请参见langage规范 更新: 这是一个测试,我似乎没有得到你所描述的 package generics; import static org.junit.Assert.*; impo

我把一个类声明为

class Heap extends ArrayList<Element>

对于这些变量,父变量的泛型类型将被删除,并简单地表示为
ArrayList
。为什么会发生这种情况?

这是在没有类型参数的情况下编写的泛型的行为。您至少应该将遗留代码转换成类似堆的东西

关于这方面的更多细节,请参见langage规范

更新:

这是一个测试,我似乎没有得到你所描述的

package generics;

import static org.junit.Assert.*;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;

import org.junit.Test;

public class HeapTest {

public static class Heap<T> extends ArrayList<String> {}

    @Test
    public void test() {
        Heap h = new Heap<>();
        Type sc = h.getClass().getGenericSuperclass();
        assertTrue(sc instanceof ParameterizedType);

        ParameterizedType pt = (ParameterizedType) sc;
        assertEquals(1, pt.getActualTypeArguments().length);

        assertSame(String.class, pt.getActualTypeArguments()[0]);

        Class<?> clazz              = (Class<?>) pt.getRawType();
        Method method               = clazz.getMethod("get", int.class);

        TypeVariable<?> rt          = (TypeVariable<?>) method.getGenericReturnType();
        String name                 = rt.getName();

        Class<?> arrayListClass     = (Class<?>) pt.getRawType();

        int i = 0;
        for (TypeVariable<?> tv : arrayListClass.getTypeParameters()) {
            if (tv.getName() == name) {
                break;
            }
            i ++;
        }

        Type actualReturnType       = pt.getActualTypeArguments()[i];
        assertSame(String.class, actualReturnType);
    }

}
包泛型;
导入静态org.junit.Assert.*;
导入java.lang.reflect.ParameterizedType;
导入java.lang.reflect.Type;
导入java.util.ArrayList;
导入org.junit.Test;
公共类HeapTest{
公共静态类堆扩展了ArrayList{}
@试验
公开无效测试(){
Heap h=新堆();
类型sc=h.getClass().getGenericSuperclass();
assertTrue(参数化类型的sc实例);
ParameteredType pt=(ParameteredType)sc;
assertEquals(1,pt.getActualTypeArguments().length);
assertSame(String.class,pt.getActualTypeArguments()[0]);
类clazz=(类)pt.getRawType();
方法Method=clazz.getMethod(“get”,int.class);
TypeVariable rt=(TypeVariable)方法。getGenericReturnType();
String name=rt.getName();
类arrayListClass=(类)pt.getRawType();
int i=0;
对于(TypeVariable tv:arrayListClass.getTypeParameters()){
if(tv.getName()==name){
打破
}
i++;
}
类型actualReturnType=pt.getActualTypeArguments()[i];
assertSame(String.class,actualReturnType);
}
}

我不知道该类是如何使用的,但我不禁想知道为什么它会扩展ArrayList?如果只声明它
类Heap
,并让ArrayList成为一个内部容器,不是更好吗?同样看到您的代码片段,我假设您希望在某个地方返回真正的类型,而不是Heap。尽管可能,在这种情况下使用泛型可能是一种反模式。我在语言规范中找不到它。它只说“原始类型是没有任何类型参数的泛型类或接口的名称”,但这里的原始类型是“Heap”,即使没有参数化,它仍然是“ArrayList”。我找不到任何明确提到使用raw类型会导致父类上的类型擦除或使父类也变为raw。您能帮我一下吗?您的遗留代码在单独的jvm中执行?请给出更多的示例代码。它的遗产更多地是在我还没有想到这个类应该是泛型的时候编写的。事实上,它是我在大约两周前写的,我完全能够将所有声明为原始类型的变量实例重构为泛型类型。我最后做的就是去掉了一个通用的。所以我请求的不是关于这个特定用例的帮助,而是理解编译器的这种行为,因为我找不到它的指定位置。嗨,不,我没有。谢谢你的通知,我明白你的意思。甚至可以编写
Heap h=new Heap()并且测试仍然会成功。但是
h.get(0)
的返回值类型是
对象
,而不是
字符串
。这就是我不能理解的。
Heap heap;
package generics;

import static org.junit.Assert.*;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;

import org.junit.Test;

public class HeapTest {

public static class Heap<T> extends ArrayList<String> {}

    @Test
    public void test() {
        Heap h = new Heap<>();
        Type sc = h.getClass().getGenericSuperclass();
        assertTrue(sc instanceof ParameterizedType);

        ParameterizedType pt = (ParameterizedType) sc;
        assertEquals(1, pt.getActualTypeArguments().length);

        assertSame(String.class, pt.getActualTypeArguments()[0]);

        Class<?> clazz              = (Class<?>) pt.getRawType();
        Method method               = clazz.getMethod("get", int.class);

        TypeVariable<?> rt          = (TypeVariable<?>) method.getGenericReturnType();
        String name                 = rt.getName();

        Class<?> arrayListClass     = (Class<?>) pt.getRawType();

        int i = 0;
        for (TypeVariable<?> tv : arrayListClass.getTypeParameters()) {
            if (tv.getName() == name) {
                break;
            }
            i ++;
        }

        Type actualReturnType       = pt.getActualTypeArguments()[i];
        assertSame(String.class, actualReturnType);
    }

}