Java泛型测试疑问:为何代码1输出"a"而代码2抛出异常?
Java泛型类型擦除导致的行为差异分析
先看两段测试代码:
代码1
public class Main { public static void main(String[] args) { Convert<String, Integer> c = new Convert<>(); // Integer number = c.convert("a"); System.out.println(c.convert("a")); } static class Convert<E, T> { public T convert(E element) { return (T) element; } } }
代码2
public class Main { public static void main(String[] args) { Convert<String, Integer> c = new Convert<>(); Integer number = c.convert("a"); System.out.println(number); } static class Convert<E, T> { public T convert(E element) { return (T) element; } } }
两者的核心差异在于:代码1直接将convert方法的返回值传入System.out.println,而代码2先将返回值赋值给Integer类型变量,再执行输出。
根本原因:Java泛型的类型擦除机制
Java泛型是编译期检查特性,运行时所有泛型参数都会被擦除为最顶层的父类型(这里E和T都会被擦除为Object)。编译后Convert类的convert方法实际等价于:
public Object convert(Object element) { return element; // 这里的(T)强转在运行时无实际作用,因为T已经被擦除为Object }
代码1能正常输出的逻辑
当调用System.out.println(c.convert("a"))时:
convert方法返回的是原始的String对象"a"——所谓的(T) element强转在运行时只是把String转成Object,没有实际类型变更System.out.println调用的是接受Object参数的重载方法,它会直接调用对象的toString()方法输出,不需要将对象转换为Integer,因此不会触发类型转换校验,自然不会抛出异常。
代码2抛出异常的逻辑
当执行Integer number = c.convert("a")时:
- 编译期编译器会根据泛型声明
Convert<String, Integer>,自动插入一个隐式强制类型转换,把convert返回的Object转成Integer - 运行时,实际返回的对象是
String类型,无法转换为Integer,因此抛出ClassCastException。
内容的提问来源于stack exchange,提问作者BrisS
相关产品推荐
相关产品推荐

