如何将Object数组转换为整数数组数组

时间:2013-09-17 01:29:55

标签: java

这是一个人为的例子,可以解决我遇到的情况,但基本上,我有一个对象数组,实际上包含整数数组,我正在尝试这样做。这是一个模拟这种情况的代码片段:

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

有没有办法在不复制数组的情况下执行此操作(我可能不想这样做,因为foo在生产中会非常大)?如果没有,为什么不呢?

3 个答案:

答案 0 :(得分:11)

您无法通过强制转换来更改Java对象的内部类型。这包括数组。对象的类型在分配对象时是固定的,不能更改。

因此,将Object[]转换为int[][]将无法正常工作。

在这种情况下,虽然int[][]Object[]的子类型,但这不足以在运行时允许类型转换。 JLS(5.5.3. Checked Casts at Run Time)中的实际规则是:

  

“这是检查对象的运行时类型R是否与类型T兼容的算法,类型T是在转换运算符中指定的类型的擦除(第4.6节)。如果运行抛出了时间异常,它是ClassCastException。“ ...

     

“如果R是表示数组类型RC []的类,即RC类型的组件数组:”

     
      
  • “如果T是数组类型TC [],即TC类型的组件数组,则抛出运行时异常,除非满足下列条件之一:”

         
        
    • “TC和RC是相同的原始类型。”

    •   
    • “TC和RC是引用类型,类型RC可以通过递归应用这些运行时规则来转换为TC。”

    •   
  •   

在这种情况下,TC为int[],RC为ObjectObject 无法投放到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方法中明确覆盖它们,等等。

答案 1 :(得分:1)

由于foo是对象数组,因此它意味着它可以包含任何内容,而不仅仅是整数数组,因此编译器无法将其转换为整数数组,因为您知道它在内部。

如果您想使用int[][] bar引用,则必须先创建单独的int [3][]数组,然后将foo的内容复制到该数组。

答案 2 :(得分:1)

您需要在访问时转换每个对象。

    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中。

编辑:简化代码。