ClassCast 错误:Java 7 与 Java 8

Posted

技术标签:

【中文标题】ClassCast 错误:Java 7 与 Java 8【英文标题】:ClassCast error: Java 7 vs Java 8 【发布时间】:2014-04-18 14:11:51 【问题描述】:

这是错误还是功能?以下代码在 Java 7 中运行良好,但在 Java 8 中抛出异常:

最后一个命令在 Java8 中引发 ClassCast 异常,上面所有“等效”命令的工作方式相同。

我认为问题在于,在 Java 8 中,编译器决定在最后一行使用 String.value(char[]) 而不是 Java 7 中的 String.value(Object)。我认为这应该与向后兼容的方式相同。我错过了什么吗?

注意:正如 Marko 所说,这可能与 Java 8 中引入的目标类型推断有关。

public class Test 
    public static void main(String[] args) 
        System.out.println( getVal().getClass());  // String

        System.out.println( String.valueOf(Test.<Object>getVal()) );   // "abc"

        Object obj = getVal();
        System.out.println( String.valueOf(obj) );  // "abc"

        System.out.println( String.valueOf(getVal()) ); // 7: "abc", 8: Exception 
    

    // returns a string for simplicity; imagine that given a field, it fetches values from a database
    @SuppressWarnings("unchecked")
    public static <T> T getVal() 
        return (T) "abc";
    

Java 7 中的结果:

class java.lang.String
abc
abc
abc

Java 8 中的结果:

class java.lang.String
abc
abc
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to [C
    at Test.main(Test.java:11)

(注意:[C 是一个字符数组)

两个 Java 都在 windows 上:

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) Client VM (build 24.45-b08, mixed mode, sharing)

java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

【问题讨论】:

对我来说似乎是一个错误。 Cannot be cast to [C 你在复制/粘贴中遗漏了什么吗? @Rogue:对我来说看起来像是字符数组的表示法。 【参考方案1】:

String.valueOf 是一个重载方法,您在必须从上下文推断参数类型的上下文中使用它。另一方面,Java 8 对类型推断规则进行了重大改革;最值得注意的是,目标类型推断得到了很大改进。因此,虽然在 Java 8 之前,方法参数站点没有收到任何推断,在您的情况下默认为 Object,但在 Java 8 中推断出最具体的适用类型,在这种情况下为 char[]

但是,请记住,在这两种情况下,您使用的习惯用法基本上都被破坏了,因此编译器输出的更改可能应该被指定为“陷阱”,而不是“错误”。

不幸的是,未经检查的强制转换有时是不可避免的,但我想不出任何情况下推断不是从 Class 对象反射创建的东西的类型本身(而不是类型参数)是有意义的.因此,您实际上不太可能处于此处显示的位置,您可以根据调用站点上可接受的参数类型推断类型。此外,使用重载方法这样做肯定会被破坏,将参数类型的选择留给推理。这只能“偶然”起作用。

【讨论】:

虽然执行示例代码所做的事情几乎没有意义,但如果这反映了 Java 错误,则该错误可能会影响 确实 有意义的代码,或者可能影响遗留代码这没有意义,但无论如何都需要维护。绝对值得弄清楚造成这种差异的原因。 无论是哪一个推论似乎都不是显而易见的“正确的”,所以我不会急于将其标记为错误。如果遗留代码依赖于这种偶然的推断,它应该很好地修复。 同意。恕我直言,这里唯一的错误是(T) "abc" 第二种情况受目标类型推断的影响,这在 Java 7 中不存在。这可能是一个线索,char[] 是“最具体的类型”,在该位置是合法的。 这就是为什么我认为没有任何令人信服的理由来抱怨 Java 7 和 8 之间编译器输出的变化。编译器只是向您展示了 unchecked cast警告一直存在是有充分理由的。

以上是关于ClassCast 错误:Java 7 与 Java 8的主要内容,如果未能解决你的问题,请参考以下文章

处理自定义图像视图时出现 Classcast 异常

Hive JDBC 错误:java.lang.NoSuchFieldError:HIVE_CLI_SERVICE_PROTOCOL_V7

使用模式加载数据时出现 Apache Pig ClassCast 异常

(更新:如何在 sqflite 中存储 List<String> 数据类型) sqflite 错误:DatabaseException(java.lang.String 无法转换为 jav

Centos6.7搭建java环境部署web项目

jdk1.6与1.7的区别?