Java:在某些情况下ClassCastException

时间:2013-09-12 14:43:13

标签: java casting

我有以下代码:

static Object f(Object x) {
    x = (Integer) 1234; // <- it runs OK (why?)
    System.out.println(x);
    return x;
}

public static void main(String[] args) {

    HashMap<String, String> before = new HashMap<String, String>();
    before.put("a", "b");

    HashMap<String, String> after = (HashMap<String,String>) f(before); // <- it fails
    System.out.println(after);
}

这是我的输出:

1234
Exception in thread "main" java.lang.ClassCastException: 
java.lang.Integer cannot be cast to java.util.HashMap

为什么从HashMap到Intger的运行没有错误?

3 个答案:

答案 0 :(得分:6)

  

为什么从HashMap到Integer的运行没有错误?

您不是从HashMap转换为Integer。您正在向int投射auto-boxed Integer

x = (Integer) 1234;

1234是一个int字面值,当您尝试将其用作参考类型时会自动装入Integer


然后,您返回Integer并获得ClassCastException,因为它无法转换为HashMap

return x;

返回1234,然后在此处投射

(HashMap<String,String>) f(before)

失败了。


这里可能存在概念错误。

Object x定义了一个可以保存对任何类型对象的引用的框。

f(myHashMap)启动一个函数调用,使用哈希映射的引用填充框x

x = (Integer) 1234会抛出框中的内容,并将其替换为对Integer的引用。这是合法的,因为声明Object x确定该框可以包含对任何对象的引用(或者没有:null)。

然后,您从x返回f,其返回类型为Object并在此处使用

HashMap<String, String> after = (HashMap<String, String>) f(before)

获取可以包含任何内容的框的内容,并确保它可以放在名为after的只能包含HashMap<?,?>的框中。

这不起作用,因为f(before)返回的引用不适合该框。因此在运行时发生异常。


您可以将程序缩减到下面,以了解正在发生的事情。

Object x = (Integer) Integer.valueOf(1234);               // Unnecessary cast.
HashMap<String, String> m = (HashMap<String, String>) x;  // Fails due to type-unsafe cast.

如果你不使用Object,你可能会得到编译器解释的问题

Integer x = (Integer) Integer.valueOf(1234);
HashMap<String, String> m = (HashMap<String, String>) x;

答案 1 :(得分:1)

1. x = (Integer) 1234; // <- it runs OK (why?)

此处进行了自动装箱,因此int转换为Integer对象,然后转换为Object。由于ObjectInteger的超级类型,因此可以。

2.HashMap<String, String> after = (HashMap<String,String>) f(before); // <- it fails

此处f()方法返回Object,您尝试将其转换为IntegerInteger不是Object的超级类型。所以你得到了ClassCastException

根据ClassCastException

  

抛出以指示代码已尝试将对象强制转换为不是实例的子类。例如,以下代码生成ClassCastException:

 Object x = new Integer(0);
 System.out.println((String)x);

答案 2 :(得分:0)

x =(整数)1234; //发生了自动装箱。编译器将原始int转换为Integer。 看起来f()总是返回Objcet,它是一个整数。而不是你试图把它投射到HashMap。编译器不会抱怨您尝试将Object(f()返回值的引用类型)强制转换为HashMap。但是对象类型是Integer,它在运行时失败。