Java中的对象类型和引用数组

时间:2012-10-06 23:57:28

标签: java arrays object

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

7 个答案:

答案 0 :(得分:13)

  

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

这一切都是正确的,并解释了为什么你可以进行作业

a[0] = b;

没有编译器的任何投诉。

  

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

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

  • aObject[] - 这是Object s
  • 的数组
  • a[0]Object
  • a[0][0] - 现在您正尝试在Object上使用数组下标。编译器不知道Object实际上是一个数组,所以它会抱怨。

答案 1 :(得分:10)

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

如果您知道某些内容总是某种类型但编译器无法解决,您可以通过插入显式转换来解决此问题。

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

答案 2 :(得分:7)

你是对的,Java中的数组始终是Objects,但Objects并不总是数组,因此会出现编译错误,因为aObject[](一维)。你无法访问

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)的返回类型为Object[],然后您可以访问“{1}}的”第二层“阵列。

答案 3 :(得分:4)

由于Java中的数组是一个对象,所以第一个和第二个赋值将把你的数组存储为Object数组的第一个元素。

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

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

因为[0]是一个对象.. 所以,你显然无法访问这样的东西: -

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

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

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

答案 4 :(得分:4)

执行:

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

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

答案 5 :(得分: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;”。

答案 6 :(得分:1)

你正在做的一切都等同于这个

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

也不编译。