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
答案 0 :(得分:13)
我的理解是数组是Java中的对象,因此是Object类型的子类。我的进一步理解是,2-dim数组被实现为对数组的引用数组。
这一切都是正确的,并解释了为什么你可以进行作业
a[0] = b;
没有编译器的任何投诉。
因此我不明白为什么我的a [0] [0]在上面的代码中没有产生条形。
好的,我们来看看这个表达式中的类型:
a
是Object[]
- 这是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
并不总是数组,因此会出现编译错误,因为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
)的返回类型为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]);
也不编译。