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);
}
}