ClassCast 错误:Java 7 与 Java 8 [英] ClassCast error: Java 7 vs Java 8

查看:17
本文介绍了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[]) 而不是 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".

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

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆