java - ClassCast 错误 : Java 7 vs Java 8

标签 java generics casting java-8

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

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

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

注意:正如 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)

最佳答案

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

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

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

关于java - ClassCast 错误 : Java 7 vs Java 8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23155907/

相关文章:

扩展类的 Java 泛型未检查警告

java - java中Jtable到TextArea

java - 通用类枚举返回类型

c# - 致专家:此代码有何区别?

c# - 将包含数组的对象显式转换为数组

Java - 如何避免在 divide 和 cast to int 期间丢失精度?

java - 如何更改菜单栏中子菜单的标签颜色?

java - 获取 Eclipse 启动的进程的 PID

typescript - 获取用 typescript 写的

java - 如何从 int 转换为 byte,然后使用位移运算符