You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Java原始类型会擦除已具体化泛型成员的类型?

原始类型使用时,为何已具体化的泛型成员也被擦除?

示例代码

import java.util.ArrayList;
import java.util.List;

public class MyTemplate<T> {

    T parameterizedObj;
    List<String> stringList;

    public static void main(String[] args) {
        String a = new MyTemplate().getStringList().get(0);
    }

    public List<String> getStringList() {
        if (stringList == null) {
            stringList = new ArrayList<>();
            stringList.add("Hello");
        }
        return stringList;
    }
}

编译错误

/home/***/test/src/main/java/MyTemplate.java:10:56
java: incompatible types: java.lang.Object cannot be converted to java.lang.String

疑问

当在第10行以new MyTemplate()的形式将MyTemplate作为原始类型使用时,能理解T parameterizedObj的类型会被擦除为Object,但无法理解已被具体化为List<String>的List<String> stringList为何会被擦除为List。查阅了原始类型和类型擦除的相关文档,未找到针对这类场景的说明。

解答

这是Java原始类型的规则:只要将泛型类作为原始类型使用,整个类的所有泛型相关信息都会被完全擦除,不仅限于类本身的类型参数T。

换句话说,当你用new MyTemplate()创建原始类型实例时,编译器会忽略这个类中所有的泛型签名——哪怕成员变量或方法返回值用的是具体的泛型类型(比如List<String>),也会被退化为擦除后的原始类型(List)。所以getStringList()的返回值会被视为List,调用get(0)自然返回Object,无法直接赋值给String,导致编译错误。

解决方法

只需避免使用原始类型,改用带类型参数的实例化方式即可:

  • 使用菱形语法(Java 7+支持):new MyTemplate<>()
  • 显式指定类型参数:new MyTemplate<Object>()

这样编译器会保留List<String>的类型信息,get(0)返回的就是String,编译错误会消失。

内容的提问来源于stack exchange,提问作者Fengtao Ding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:52:33