【问题标题】:Catching ClassCastException in a generic method when doing generic cast在进行泛型转换时在泛型方法中捕获 ClassCastException
【发布时间】:2017-11-29 17:03:36
【问题描述】:

假设我有一个方法

@SuppressWarnings("unchecked")
public <T extends Number> T getNumber() {
   try {
      return (T)number; 
   } catch (ClassCastException e) {
      return null;
   }
}

假设numberInteger的一个实例,调用方法如

Float f = getNumber();

结果为@​​987654325@。

我知道(不知何故)这是因为 类型擦除,但有人可以提供更深刻的解释,为什么异常会升级到分配级别并且在方法内部无法捕获?

注意:我确实有版本 public &lt;T extends Number&gt; T getNumber(Class&lt;T&gt; classT),它检查来自 classT 的类型,但希望摆脱通过 classT 并不再怀疑上述问题。

【问题讨论】:

    标签: java generics casting classcastexception type-erasure


    【解决方案1】:

    类型擦除后,return (T)number 变为return (Number)number(因为NumberT 的类型绑定),这不会引发异常(因为numberInteger 的一个实例)。

    另一方面,任务

    Float f = getNumber();
    

    编译成

    Float f = (Float) getNumber();
    

    因为getNumber() 返回一个Number,它不能在没有强制转换的情况下分配给Float 变量。

    getNumber() 不是Float 时,此演员表会抛出ClassCastException

    4.6. Type Erasure

    类型擦除是从类型(可能包括参数化类型和类型变量)到类型(绝不是参数化类型或类型变量)的映射。我们写 |T|用于类型 T 的擦除。擦除映射定义如下...

    类型变量的擦除(第 4.4 节)是其最左边界的擦除。

    【讨论】:

    • 感谢清晰易懂的答案(你怎么能写得这么快又清晰,我羡慕……)。我假设如果我删除了`extends Number`所以&lt;T&gt;只有return (Object)number
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多