【问题标题】:Strange ClassCastException in javajava中奇怪的ClassCastException
【发布时间】:2018-01-29 11:08:41
【问题描述】:

我写了一些代码如下:

public class MyClass {
    public static void main(String[] args) {
        printIt(getLong());
        System.out.println("---------");
    }

    public static Object printIt(Object... objects) {
        System.out.println(objects[0].toString());
        return objects[0];
    }

    public static <T> T getLong() {
        return (T)Long.valueOf(1L);
    }
}

当我运行它时,它会抛出 java.lang.ClassCastException 如下:

线程“主”java.lang.ClassCastException 中的异常: java.lang.Long 不能转换为 [Ljava.lang.Object;在 com.sealinetech.MyClass.main(MyClass.java:5)

但是当我用 Evaluate Expression 调试它时,没关系 Evaluate Expression is OK

我的IDE是intellij,JDK版本是jdk1.8.0_144

【问题讨论】:

  • 您将Long 转换为Object[]。只是不要这样做。
  • 我强烈反对像您的public static &lt;T&gt; T getLong() 这样的方法签名,因为您无法从任何参数推断类型 T。典型用法有一些类型 T 的参数,例如public static &lt;T&gt; T doSomething(T arg).
  • 正如每本教科书所说的那样。当您忽略“未检查”警告时,您可能会在运行时收到奇怪的ClassCastExceptions……
  • 类似于this issue...
  • 当我运行应用程序时,它在 printIt(getLong()) 行中抛出 ClassCastException,但我将 printIt(getLong()) 复制到 Evaluate Expression 工具然后单击 Evaluate 按钮,它可以正确输出结果,就像上图一样。所以我想知道为什么java使用不同的类型推断方法。

标签: java java-8 classcastexception


【解决方案1】:

getLong 方法具有通用返回类型。在编译时编译器决定用Object[] 结果类型调用它,因为printIt 接受这个参数类型。在运行时编译器建议失败,因此您收到此错误:java.lang.Long cannot be cast to [Ljava.lang.Object

您可以使用printIt(this.&lt;Object&gt;getLong()); 指定预期类型(感谢@CoderinoJavarino)

【讨论】:

  • 在这种情况下,您可以通过明确指定类型来解决。 printIt(this.&lt;Object&gt;getLong());
  • 但是为什么我用 Evaluate Expression 调试它就可以了?
  • @Rhett : 因为不同的类型推断结果。阅读docs
【解决方案2】:

如前所述,异常来自编译器将T 解析为Object[] 而不是Object

我知道这段代码只是一个玩具示例,用于更复杂的事情。根据实际情况,已经建议的替代解决方案是将类型参数T 的返回限制为选择的非数组类型。在这个简单的例子中,它可能类似于&lt;T extends Number&gt;

但是,需要指出的是,仅查看问题代码,似乎很清楚,给定方法的名称,它会返回Long,或者如果null,则可能返回long,不是一个有效值,这里去掉类型参数T 并将返回类型设置为Longlong 更有意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多