Java未指定类型边界的子类中父类泛型属性丢失原因探究
为什么子类继承原始类型泛型父类会出现类型丢失?
嗨,这个问题的核心在于Java泛型里**原始类型(Raw Type)**的特殊行为,咱们把它掰碎了说:
1. 你用了原始类型的父类
当你写public class Bar extends Foo的时候,并没有给父类Foo指定泛型参数,这就相当于把Foo当成了原始类型来使用。原始类型是Java为了兼容泛型出现之前的老代码而保留的特性,但它会直接“废掉”父类的所有泛型相关上下文——哪怕某个成员和泛型参数X完全没关系。
2. 原始类型的“传染性”导致方法退化
虽然父类里的stuff属性是List<String>,和泛型参数X无关,但因为你用了原始类型Foo,Java会把父类的所有方法都退化为非泛型版本:
- 原本的
List<String> getStuff()会被视为List getStuff() - 原本的
void setStuff(List<String>)会被视为void setStuff(List)
这就导致你在Bar里调用getStuff()时,拿到的是不带泛型的List而非List<String>,自然就出现了你看到的“类型丢失”现象。
3. 怎么解决?
永远避免使用原始类型,除非是迫不得已兼容老代码。正确的写法是给父类指定明确的泛型参数,比如:
public class Bar extends Foo<Object> { public Bar() { setStuff(new ArrayList<>()); } public void whatIsGoingOnHere() { for(String thing : getStuff()) { // 这里就不会有类型问题了 } } }
这样父类的方法就会保留完整的泛型类型,getStuff()依然返回List<String>,不会有类型丢失的问题。
如果你的父类Foo的泛型参数X在Bar里根本用不上,也可以考虑重构父类,把泛型参数去掉(当然这要看父类的设计初衷)。
内容的提问来源于stack exchange,提问作者mobiusinversion
相关产品推荐
相关产品推荐

