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

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"))时:

  1. convert方法返回的是原始的String对象"a"——所谓的(T) element强转在运行时只是把String转成Object,没有实际类型变更
  2. System.out.println调用的是接受Object参数的重载方法,它会直接调用对象的toString()方法输出,不需要将对象转换为Integer,因此不会触发类型转换校验,自然不会抛出异常。

代码2抛出异常的逻辑

当执行Integer number = c.convert("a")时:

  1. 编译期编译器会根据泛型声明Convert<String, Integer>,自动插入一个隐式强制类型转换,把convert返回的Object转成Integer
  2. 运行时,实际返回的对象是String类型,无法转换为Integer,因此抛出ClassCastException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:46:19