您不能通过强制转换来更改 Java 对象的内在类型。这包括数组。对象的类型在分配对象时是固定的,不能更改。
所以铸造一个Object[]
永远int[][]
不会奏效。
在这种情况下,whileint[][]
是 的子类型Object[]
,这不足以在运行时允许类型转换。JLS 中的实际规则(5.5.3. Checked Casts at Run Time)是这样的:
“这是检查对象的运行时类型 R 是否与类型 T 的赋值兼容的算法,类型 T 是强制转换运算符中命名的类型的擦除(第 4.6 节)。如果抛出运行时异常,它是一个ClassCastException
。” ...
“如果 R 是表示数组类型 RC[] 的类,即 RC 类型的组件数组:”
在这种情况下,TC 是int[]
并且 RC 是Object
并且Object
不能强制转换为int[]
. 因此你得到一个例外。
为了说明为什么会发生这种情况,请考虑这个(假设的)示例:
Object[] foo = new Object[3];
foo[0] = new Object();
int[][] bar = /* foo */
int[] mystery = bar[0];
假设可以“转换” 的值foo
,那么mystery
变量应该指向什么?这不可能是int[]
因为我们没有分配一个。它不能是一个Object
实例,因为这会破坏静态类型。
事实上,“强制转换”必须是非法的,否则 Java 的静态类型系统就会崩溃。
您的示例和我的示例之间的区别在于 foo 实际上不是整数数组的数组,而在我的示例中它是。为什么虚拟机看不到对象的“实际”类型?
关键是静态类型(主要)由编译器而不是 JVM 强制执行。虽然 JVM 可以(理论上)确定类型在运行时是正确的(如果不是,则抛出异常),但编译器无法做到这一点,因为它通常无法确定类型将是什么。
不幸的是,我实际上并没有自己创建数组。我从另一个函数中得到它,据我所知,它Object[]
不是int[][]
我无法控制的一些序列化的副作用。
不幸的是,您必须复制数组...或将其用作 anObject[]
并将元素转换int[]
为使用它们;例如
Object[] foo = new Object[3];
foo[0] = new int[] { 1, 2, 3 };
foo[1] = new int[] { 4, 5, 6 };
foo[2] = new int[] { 7, 8, 9 };
...
int nine = ((int[]) (foo[2]))[2];
Java中没有“相信我,这确实是一个int[][]
”选项。
如果这是序列化的副作用,那么序列化就被破坏了……在某种意义上。当然,标准的 Java 对象序列化协议/实现不会发生这种情况。这保留了对象的类型......除非您在readObject
/writeObject
方法等中明确覆盖它们。