在Java中,我可以编译代码
Object[] obj = {new Object[1], new Object[2]};
但是我无法编译
Object obj = {new Object(), new Object()};
在第一个示例中,我声明了一个由对象
组成的一维数组
并为其分配了一个二维数组
。在第二个示例中,我声明了一个对象
并为其分配了一个一维数组。如果Java数组扩展了
对象
,那么为什么第二个代码片段无法编译?为什么第一个可以编译?在Java中,我可以编译代码
Object[] obj = {new Object[1], new Object[2]};
但是我无法编译
Object obj = {new Object(), new Object()};
在第一个示例中,我声明了一个由对象
组成的一维数组
并为其分配了一个二维数组
。在第二个示例中,我声明了一个对象
并为其分配了一个一维数组。对象
,那么为什么第二个代码片段无法编译?为什么第一个可以编译?将数组分配给对象并不是问题,但您必须像这样创建数组
Object obj = new Object[] { new Object(), new Object[2] };
否则编译器无法辨别这是一个对象数组而不是其他类型的数组。Object obj = {new Object(), ...}
返回一个数组,就像“多重指针数组”,而 new ...
返回一个指向 new
后面的任何东西的指针。所以 Object obj = new Object[]{...}
返回一个指向数组的指针,而 Object obj = {...}
返回一个数组。 - DanyelObject[] a; Object[] b; a = new Object[] { new Object(), new Object() }; b = a; b[0] = null; System.out.println("a[0] is null? " + (a[0] == null));
如果变量实际上包含数组,那么b = a;
这一行必须是一个数组复制操作,不是吗?因此对b[0]
的赋值对a[0]
没有影响。但事实并非如此,因为Java定义了a
和b
持有引用。:-) - T.J. CrowderObject[] o = {...}
是存储在应用程序的 Stack
还是 Heap
中。我想这就是我试图了解的地方。我知道最终 o
只会是一个引用而不是实际的数组。希望你知道我的意思。 - DanyelArray
不仅仅是Object
的子类。数组还具有语言级别的语义和语法。
另外,你的第二个例子引出了一个问题:你想初始化的这两个东西会存储在哪里?你刚刚声明了一个对象,但它没有命名字段,也缺乏数字索引槽,就像数组一样。
你的第一个例子编译通过,因为你声明了一个Object
数组(即对象引用),并且你要给它初始化的元素都是对象引用(通过new Object[1]
创建单元素数组所得到的引用)。
这可能也会有所帮助: Java实际上并没有二维数组,尽管有一些方便的语法使其看起来像是有的。它有单(一维)数组和单(一维)数组(等等)。
int[] arr = {1,2};
Object obj = arr;
以下是代码:
Object obj = {1,2};
Object[] obj = {1,2};
因为元素的类型已经提供(即Object
),编译器会检查1
、2
的类型是否与Object
相匹配(由于Integer
是Object
的子类型,因此匹配成功)。
无法编译
Object obj = {new Object(), new Object()};
因为 obj 不是一个数组,所以要像这样声明
Object[] obj = {new Object(), new Object()};
或者
Object obj = new Object[] { new Object(), new Object() };
在下面的对话后进行了编辑
Object
变量可以持有数组的引用,因为数组是从Object
派生而来的。您不必声明变量Object[]
(尽管如果这样做可能更有用)。只是在创建和初始化数组时,编译器需要知道它是什么类型的数组,因此出现了Robber提供的语法。 - T.J. CrowderArray
不是String
的子类。 - T.J. Crowder