[英]How can I cast an Object array to an array of arrays of integers
这是一个人为的例子,可以解决我遇到的情况,但基本上,我有一个对象数组,实际上包含整数数组,我正在尝试这样做。 这是一个模拟这种情况的代码片段:
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[][] bar = (int[][]) foo;
当我尝试这样做时,我Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[I
得到异常Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[I
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[I
有没有办法在不复制数组的情况下执行此操作(我可能不想这样做,因为foo
在生产中会非常大)? 如果没有,为什么不呢?
您不能通过强制转换来更改Java对象的内部类型。 这包括数组。 对象的类型在分配对象时是固定的,不能更改。
因此将Object[]
为int[][]
将永远不会起作用。
在这种情况下,虽然int[][]
是Object[]
的子类型,但这不足以在运行时允许类型转换。 JLS中的实际规则( 5.5.3。运行时检查的转换 )是这样的:
“这是用于检查对象的运行时类型R是否与类型T兼容的算法,类型T是在转换运算符中指定的类型的擦除(第4.6节)。如果抛出运行时异常,这是一个
ClassCastException
。“ ...“如果R是表示数组类型RC []的类,即RC类型的组件数组:
“如果T是数组类型TC [],即TC类型的组件数组,则抛出运行时异常,除非满足以下条件之一:”
“TC和RC是相同的原始类型。”
“TC和RC是引用类型,类型RC可以通过递归应用这些运行时规则来转换为TC。”
在这种情况下,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实际上并不是整数数组的数组,而在我的情况下则是。 为什么VM无法看到对象的“实际”类型?
关键是静态类型(主要)由编译器强制执行,而不是由JVM强制执行。 虽然JVM可以(在理论上)计算出该类型是在运行时确定(并抛出异常,如果他们都没有),编译器不能做到这一点,因为它不是一般的判断是什么类型的都将是。
不幸的是,我实际上并没有自己创建阵列。 我从另一个函数得到它而且,就我所知,
Object[]
而不是int[][]
是我无法控制的某些序列化的副作用。
不幸的是,您必须复制数组...或将其用作Object[]
并将元素转换为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
方法中显式地覆盖它们,等等。
因为foo
是对象数组,所以它意味着它可以包含任何东西,而不仅仅是整数数组,所以编译器不允许你将它转换为整数数组,因为你知道它在里面。
如果要使用int[][] bar
引用,则必须首先创建单独的int [3][]
数组,并将foo
内容复制到该数组。
您需要在访问时转换每个对象。
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[] foo2 = (int[])foo[2];
System.out.println("foo[2,2]="+((int[])foo[2])[2]);
如果您认为内容可能是非整数的话,您也应该将它包装在try ... catch
。
编辑:简化代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.