泛型通过编译期类型检查消除运行时ClassCastException风险,使集合add和get操作均受类型约束,支持for-each和lambda的类型推导,但受限于类型擦除,无法使用基本类型、运行时获取泛型信息、创建泛型数组或重载泛型方法。
泛型让 Collection 不再依赖运行时类型检查
Java 集合类(如 ArrayList、HashMap)在设计之初是面向 Object 的,所有元素都以 Object 类型存入。这意味着你往 ArrayList 里塞一个 String,取出来时还得手动强转:(String) list.get(0)。一旦类型写错,编译能过,但运行时抛 ClassCastException——这种错误本该在编译期就被拦住。
泛型的实质是编译期语法糖,它让集合声明时就绑定元素类型,比如 ArrayList。编译器据此做类型推导和检查,把不合法的 add(new Date()) 直接报错,而不是等运行时才发现。
关键点在于:泛型擦除后,字节码里仍是 Object,但编译器已为你加了隐式强转和类型约束,相当于把“信任程序员”的责任,换成了“由工具保障”。
get() 和 add() 的行为差异暴露了无泛型的风险
看这两个操作的底层逻辑:
立即学习“Java免费学习笔记(深入)”;
-
get(int index)返回Object,调用方必须自己转型——容易漏、容易错、IDE 不提示 -
add(E e)接收泛型参数,编译器会校验传入值是否匹配声明类型,不匹配直接编译失败
也就是说,无泛型时,add 是“放行”的,而 get 是“甩锅”的。泛型把两端都管住了:既不让错类型进,也不让用户裸着拿。
常见错误现象:ArrayList list = new ArrayList(); list.add(1); list.add("hello"); String s = (String) list.get(0); —— 运行时报 ClassCastException,因为索引 0 是 Integer。