ClassCast 错误:Java 7 与 Java 8

2022-09-01 12:12:58

这是一个错误或功能吗?以下代码在 Java 7 中运行良好,但在 Java 8 中引发异常:

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

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

答案 1

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

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

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


答案 2

推荐