0

我有以下代码:

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 的转换运行没有错误?

4

3 回答 3

6

为什么从 HashMap 转换为 Integer 运行没有错误?

您不是从 HashMap 转换为 Integer。您正在将自动装箱 int投射到Integer.

x = (Integer) 1234;

1234是一个文字,当您尝试将其用作引用类型时,int它会自动装箱。Integer


然后你返回它Integer并得到 aClassCastException因为它不能被强制转换为 a 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<?,?>s 的盒子中。

这不起作用,因为返回的引用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;
于 2013-09-12T14:45:09.480 回答
1

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

在这里,自动装箱完成,因此int被转换为Integer对象,然后被强制转换为Object。因为它Object是超级类型,Integer所以没关系。

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

这里f()方法返回Object,您正试图将其转换为Integer. Integer不是超级类型的Object。所以你得到了ClassCastException

根据ClassCastException

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

 Object x = new Integer(0);
 System.out.println((String)x);
于 2013-09-12T14:47:29.583 回答
0

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

于 2013-09-12T14:49:16.013 回答