桥接方法的getGenericReturnType()返回擦除类型(如Object),真实方法才返回完整泛型信息;应优先使用getDeclaredMethods()获取方法,过滤isBridge()==false后调用getGenericReturnType()。

桥接方法会让 getGenericReturnType() 返回擦除后的类型,而真实方法才能返回带泛型信息的完整类型。这是泛型擦除与编译器补全机制共同作用的结果,不是 bug,但必须识别并绕过它。
桥接方法上 getGenericReturnType() 返回的是“假泛型”
比如父类定义 <T> T get(),子类实现 String get(),编译后子类会生成一个桥接方法:public Object get() { return this.get(); }
这个桥接方法的 getGenericReturnType() 返回 Object(即 Class<Object>),而不是 String 或任何泛型结构。它本质上是编译器为满足 JVM 类型系统而插入的“适配器”,不承载原始泛型语义。
真实方法才保留原始泛型签名
你手动写的 String get() 方法(非桥接)才是真实方法。对它调用 getGenericReturnType(),返回值是 Class<String>;如果是 <T extends Number> T getValue(),则返回 TypeVariable,其 getName() 是 "T",getBounds() 可查到 Number.class。
- 真实方法的
getReturnType()和getGenericReturnType()往往一致(如都返回String.class),或后者提供更精确的泛型结构(如ParameterizedType) - 桥接方法的
getReturnType()与getGenericReturnType()通常相同,且都是擦除后类型(如Object.class) - 不能仅靠返回类型是否为
Object判断——协变返回类型(如子类重写返回StringBuilder)也会产生桥接,但返回类型不是Object
如何安全获取泛型返回类型
关键不是“避开桥接方法”,而是“优先选真实方法”。操作逻辑如下:
- 先用
Class.getDeclaredMethods()获取当前类声明的所有方法(不含继承来的) - 遍历每个
Method,用m.isBridge()过滤掉桥接方法 - 对剩余非桥接方法调用
getGenericReturnType()—— 这才是可信的泛型返回类型 - 若目标方法来自父类或接口(如 DAO 的
<T> T findById(ID)),需结合m.getDeclaringClass().getTypeParameters()与实际调用上下文(如子类声明的泛型实参)做类型映射
常见误用与规避建议
直接对反射结果调用 getGenericReturnType().toString() 容易触发 MalformedParameterizedTypeException,尤其在桥接方法或未解析的 TypeVariable 上。稳妥做法:
立即学习“Java免费学习笔记(深入)”;
- 永远先判断
method.isBridge() == false再读取泛型返回类型 - 对返回的
Type做类型检查:是Class就直接用;是ParameterizedType再调getActualTypeArguments();是TypeVariable则需结合宿主类泛型签名推导 - 避免用
getMethod("xxx", ...)查找——它可能命中桥接方法;改用getDeclaredMethod("xxx")+ 显式过滤


















