本文介绍了ClassCast错误:Java 7和Java 8的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is this a bug or feature? The following code runs fine in Java 7 but throws an exception in Java 8:

最后一个命令在Java8中抛出ClassCast异常,上述所有等效同样的方式。

The last command throws a ClassCast exception in Java8, all the "equivalent" commands above work the same way.

问题是,在Java 8中,编译器决定使用 String.value(char []) / code>在最后一行,而不是 String.value(Object)在Java 7。我认为这应该行为相同的方式向后兼容。我缺少一些东西?

The problem, I think, is that in Java 8, the compiler decides to use String.value(char[]) on the last line instead of String.value(Object) as in Java 7. I would think this should behave the same way for backward compatibility. Am I missing something?

注意:由于Marko建议这可能与Java 8中引入的目标类型推断有关。

Note: As Marko suggested this is probably related to target type inference introduced in 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中的结果:

Result in Java 7:

class java.lang.String
abc
abc
abc

Java 8中的结果:

Result in 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是字符数组]

(Note: [C is an array of chars)

两个Java都在Windows上:

Both Java's are on 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 []

String.valueOf is a heavily overloaded method and you are using it in a context where the argument type must be inferred from the context. On the other hand, the rules of type inference have received a significant overhaul in Java 8; most notably target type inference has been much improved. So, whereas before Java 8 the method argument site did not receive any inference, defaulting to Object in your case, in Java 8 the most specific applicable type was inferred, in this case char[].

但是,请记住,在这两种情况下,编译器输出中的改变应该被指定为陷阱,而不是错误。

However, keep in mind that in both cases the idiom you used is essentially broken so the change in compiler output should perhaps be designated as a "pitfall", but not a "bug".

不幸的是,取消选中的转换有时是不可避免的,但我不能想到推断类型本身(而不是类型参数)而不是从对象创建的。因此,你不太可能真正发现自己在这里显示的位置,在那里你推断类型基于可接受的参数类型在调用站点。此外,使用重载方法这样做是肯定打破的,留下参数类型的选择来推断。这只能偶然工作。

The unchecked cast is unfortunately sometimes unavoidable, but I can't think of any case where it makes sense to infer the type itself (as opposed to a type parameter) of something which is not created reflectively from a Class object. Therefore you are not likely to actually find yourself in the position shown here, where you infer the type based on the acceptable argument types on the call site. Moreover, it is certainly broken to do this with an overloaded method, leaving the choice of argument type to inference. This can only work "by accident".

这篇关于ClassCast错误:Java 7和Java 8的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-06 04:57