【问题标题】:JDK8 type inference issueJDK8 类型推断问题
【发布时间】:2023-03-17 01:17:01
【问题描述】:

由于类型推断,我正在尝试运行以下在 JDK8 下编译良好的代码:

public static <A,B> B convert(A a) {
  return (B) new CB();
}
public static void main(String[] args) {
  CA a = new CA();
  CB b = convert(a); //this runs fine
  List<CB> bl = Arrays.asList(b); //this also runs fine
  List<CB> bl1 = Arrays.asList(convert(a)); //ClassCastException here
}

但是,运行它会抛出 ClassCastException: CB cannot be cast to [Ljava.lang.Object, but the CB b = convert(a) 工作正常。

知道为什么吗?

【问题讨论】:

  • 等等,convert 到底在做什么?它的参数被忽略了,所以传入的内容无关紧要。
  • 您使用哪个 JRE 版本?我得到一个带有 1.8.0_92 的 java.lang.VerifyError: Bad type on operand stack。顺便说一句,使用类型见证对我有用:List&lt;CB&gt; bl1 = Arrays.asList(Test.&lt;CA, CB&gt;convert(a));
  • @StefanZobel 确实可行,但我有大约 150 次使用,手动更改并不容易 - 我希望 JDK8 会自动进行推理
  • 使用 1.8.0_92 和 1.8.0_102 的 javac 我也获得了 CCE。
  • 这是一个完全有效的结果。您创建了一个允许推断任意返回类型的泛型方法,因此编译器可以推断CB[] 而不是推断CB 并进行可变参数处理。

标签: java-8 javac classcastexception type-inference


【解决方案1】:

每当您创建一个带有承诺返回调用者希望的任何内容的签名的泛型方法时,您就是在自找麻烦。您应该从编译器收到“未经检查”的警告,这基本上意味着:可能会发生意外的ClassCastExceptions。

你期望编译器推断

List<CB> bl1 = Arrays.asList(YourClass.<CA,CB>convert(a));

而编译器实际推断出来的

List<CB> bl1 = Arrays.asList(YourClass.<CA,CB[]>convert(a));

据我所知,因为它更喜欢不需要 varargs 打包的方法调用(与 pre-varargs 代码兼容)。

这会失败,因为您的 convert 方法没有返回预期的数组类型。

【讨论】:

    猜你喜欢
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多