15
public class RefMix {
  public static void main(String[] args) {
    Object[] a = {null, "foo"};
    Object[] b = {"bar", b};
    a[0] = b;

    System.out.println(a[0][0]);
  }
}

我的理解是数组是 Java 中的对象,因此是 Object 类型的子类。我进一步的理解是,2-dim 数组是作为数组引用的数组实现的。因此我不明白为什么我的 a[0][0] 没有bar在上面的代码中产生。相反,它不编译:

RefMix.java:7: array required, but java.lang.Object found
4

7 回答 7

13

我的理解是数组是 Java 中的对象,因此是 Object 类型的子类。我进一步的理解是,2-dim 数组是作为数组引用的数组实现的。

这一切都是正确的,并解释了为什么您可以完成作业

a[0] = b;

没有来自编译器的任何抱怨。

因此我不明白为什么我的 a[0][0] 在上面的代码中没有产生 bar 。

好的,我们来看看这个表达式中的类型:

  • a是一个——这是一个sObject[]的数组Object
  • a[0]是一个Object
  • a[0][0]- 现在您正尝试在Object. 编译器不知道它Object实际上是一个数组,所以它会抱怨。
于 2012-10-07T00:03:57.917 回答
10

对象实例的运行时类型不同于静态推断的类型。编译器将尝试估计程序中每个变量的类型,以便及早捕获某些类型的错误。在这种情况下,a[0]将始终是一个数组,但编译器不知道这一点。由于您要从对象数组中获取对象,因此编译器只知道这a[0]是一个对象。因此它会引发错误。

如果您知道某些东西总是某种类型但编译器无法弄清楚,您可以通过插入显式强制转换来解决这个问题。

System.out.println(((Object[])a[0])[0]);
于 2012-10-07T00:00:09.503 回答
7

你是对的,数组总是Objects在 Java 中,但Objects并不总是数组,因此你会得到一个编译错误,因为a是一个Object[](一维)。您无法访问

a[0][0];

因为a不是二维数组(至少它没有这样声明)。但是,在这种情况下,您可以肯定,这a[0]是一个Objects. 因此,您可以这样做:

Object[] c = (Object[]) a[0];
System.out.println(c[0]);
// or directly:
System.out.println(((Object[])a[0])[0]);

会将a[0](即)的返回类型转换Object为 a Object[],然后您可以访问数组的“第二层”。

于 2012-10-07T00:08:14.833 回答
4

由于 Java 中的数组是一个对象,因此第一个和第二个分配会将您的数组存储为您的对象数组的第一个元素。

Object[] a = {null, "foo"};
Object[] b = {"bar", b};

现在,您已将对象数组的第一个元素更改a为包含值 b 而不是数组。但因为它是一个对象数组。从中出来的一切都将是对象..

由于 a[0] 是一个对象..所以,你显然不能访​​问这样的东西: -

System.out.println(a[0][0]);

您可以尝试将对象 a[0] 类型转换为对象数组..:-

System.out.println(((Object[])a[0])[0]);
于 2012-10-07T00:01:06.780 回答
4

做:

System.out.println(((Object[])a[0])[0]);

这将在运行时将对象“转换”为对象数组。

于 2012-10-07T00:02:06.083 回答
2

由于我最近做了很多 C++ 编码,我发现 Java 在类型检查方面比 C++ 严格得多。Java 将除原始类型之外的所有内容都视为 Object,但 Java 在区分 Array 和非 Array 类型方面更进了一步。在分配期间,例如“a [0] = b;” , Java 首先检查它是否是 Array 类型,然后通过常规的多态类型检查过程。如果你想让你的代码工作,你应该做...

Object[][] a = {{null}, {"foo"}};
Object[] b = {"bar", new java.util.Date()};
a[0] = b;

您可以通过查看作为参数传递给 Class.forName() 的 Java 类签名来了解 java 如何特别注意数组类型。例如,数据类型..

com.foo.Bar[][] barsIn2D;

可以在下面加载签名...

// [ => Array
// [[ => Array of Array type
// L<object>; => Object, not Array
Class.forName("[[Lcom/foo/Bar;");

如您所见,签名以“[”或“L”开头。这告诉我们它是否是一个数组优先于“Lcom/foo/Bar;”。

于 2012-10-07T09:00:07.877 回答
1

你所做的一切都相当于这个

Object a = {"bar", "foo"};
System.out.println(a[0]);

这也不能编译。

于 2012-10-07T00:22:04.407 回答