数组是原始类型还是对象(或完全是其他东西)?
Posted
技术标签:
【中文标题】数组是原始类型还是对象(或完全是其他东西)?【英文标题】:Is an array a primitive type or an object (or something else entirely)? 【发布时间】:2012-09-30 04:19:37 【问题描述】:这个问题基本上是不言自明的。我还没有找到数组的 API(除了这个Arrays,但这只是定义了一堆用于处理实际数组的静态辅助函数)。如果它没有类,这似乎表明数组不能是Object
。
然而,数组具有像 length
这样的公共字段以及像 .equals()
和 .clone()
这样可以调用的方法这一事实似乎(非常强烈地)暗示了完全相反的情况。
原始数组的奇怪表示和行为的解释是什么?
作为说明,我刚才尝试在数组的.clone()
方法上使用“Open Implementation” Eclipse 功能,希望我能够查看该方法的定义位置和方式(因为它说int[] 从 Object 中覆盖它),但它实际上导致我的整个 Eclipse 冻结并崩溃......
【问题讨论】:
【参考方案1】:请看下面的代码。它编译:
int[] arr = new int[2];
System.out.println(arr.toString());
现在,在任何原始类型上,您都不能调用 Object 类中定义的方法(toString()
)(或者,任何与此相关的方法)...因此,数组本质上是 Object
。
好的,给你:
来自JLS Section 4.3:
有四种引用类型:类类型(第 8 节)、接口 类型(第 9 节)、类型变量(第 4.4 节)和数组类型(第 10 节)。
还有,Section 10:
在 Java 编程语言中,数组是对象(第 4.3.1 节),是 动态创建,并且可以分配给 Object 类型的变量 (§4.3.2)。 Object 类的所有方法都可以在数组上调用。
所以,从第一句话来看,Array
实际上并不是一个类……它是另一种类型。但是,数组本质上是对象,虽然不是某些Class
,但它们是Array
类型。所以它们不是某个类的实例,可能是array
的对象被定义为以这种方式创建...
【讨论】:
我知道。我以前用过数组。当意识到数组的行为与实际的常规对象有何不同时,这个问题就浮现在脑海中。例如,在您的“新”声明中,您不使用new int[2]()
... 因为它不是真正的构造函数。为什么? API在哪里?解释是什么?它没有你做的那么简单。
而且我更愿意知道是否有人不喜欢我的回答,以便我可以改进它,而不是仅仅看到它的反对意见..【参考方案2】:
每个数组类型都有一个类,所以int[]
有一个类,Foo[]
有一个类。这些类是由 JVM 创建的。您可以通过int[].class
、Foo[].class
访问它们。这些类的直接超类是Object.class
public static void main(String[] args)
test(int[].class);
test(String[].class);
static void test(Class clazz)
System.out.println(clazz.getName());
System.out.println(clazz.getSuperclass());
for(Class face : clazz.getInterfaces())
System.out.println(face);
还有一个编译时子类型规则,如果A
是B
的子类型,A[]
是B[]
的子类型。
【讨论】:
优秀的答案!我现在明白为什么我现在找不到任何 API 或任何东西了。非常有趣的是 JVM 在运行时自己生成这些类。最后一个问题:如果数组是一个类的成员,就像任何其他对象一样,初始化是如何工作的?如果你说的是准确的并且 [] 只是类名的一部分,为什么不使用构造函数声明它们,即 new int[](2) vs new int[2]?int[2]
语法来自 C,Java 试图接近。
jvm 中很可能有特殊代码来处理数组初始化,这与标准对象实例化完全不同。
我就是这么想的。所以“在幕后”,编译器是提取数字并将其传递给它制作的标准构造函数,还是什么?
请注意,编译时子类型化规则破坏了类型安全***.com/a/3712419/2558896【参考方案3】:
只有我们所知道的 Java 中的这几种原始类型。基本上,我们仍然需要几个步骤来创建一个数组,例如声明、构造或根据需要进行初始化,这意味着数组确实是一个对象。
更深入一点,原始类型可以与原始值一起存储在内存中,但对象是地址(引用)。所以我们可以想象一个悖论,如果数组是原始类型,我们如何将原始值存储在内存中?我觉得和String一样,但是String是final对象,所以可以很简单的构造一个对象,String s = "s",就像原始类型一样。
【讨论】:
【参考方案4】:如此简短,是的,Object
的一个类型。据我了解,它直接从Object
扩展而来。上面有所有的 Object 方法,toString()
,hashCode()
,...加上一个特殊的暴露变量,称为length
。 java.util.Arrays
类是用于处理数组类型的实用程序类。当您添加诸如 int[]
不继承自 Object[]
之类的混乱时,这有点令人困惑。此外,与其他 Object
类型不同,数组类型没有构造函数。他们尊重new
关键字,但这通常是为了分配大小。这有点奇怪,但只是其中一种语言怪癖。
不过,要回答这个问题,是的,它们是一个对象。
【讨论】:
一个数组是一个对象...但是 int[] 不继承自 Object?这让我很困惑。而且我也对没有构造函数感到困惑,因为我们使用new
...这是如何工作的?基元数组基本上是对象和硬连线基元之间的交叉...?
no int[] 不继承自 Object[]。与 int[] 和 Object[] 一样,String[] ... 都不同,因为它们都继承自 Object,而不是 Object[]。泛型有助于编写采用数组的方法,以及我提到的 Arrays 实用程序类,但是是的,这个奇怪的怪癖会导致一些时髦的代码,有时只是为了让类型对齐
如果 int[] 不继承自 Object 并且 int[] 不是原语,它是什么? Java 的主要格言(所有对象都扩展Object
)是否不完全正确,并且数组属于单独的对象类别?
将[]
视为类名的一部分。所以有int
这是原始的。有Integer
,这是一个Object
。还有int[]
,这是Object
的另一种类型。
@Jeff 有一些信息here。虽然这个问题针对的是二维数组,但那里的答案应该能让您对机制有所了解。【参考方案5】:
Java Language Specification 应该会给你一个想法:
数组类型的直接超类是Object。
每个数组类型都实现了接口
Cloneable
和java.io.Serializable
。
Moreover:
对象是类实例或数组。
所以数组不是实例,因此您不需要构造函数来创建它们。相反,您使用Array Creation Expressions。
【讨论】:
也许我想太多了...但是不是类或类成员的东西怎么能扩展Object
?
@Jeff 我无法真正回答这个问题。也许this 有帮助。此外,还有一个有趣的答案here。
@irreputable 你的意思是 int[].class【参考方案6】:
数组是一个容器对象,包含固定数量的单一类型值。
见http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
【讨论】:
我看过那个文档,但是它的 API 在哪里呢?那是我在任何地方都找不到的。【参考方案7】:这是一个对象
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
【讨论】:
以上是关于数组是原始类型还是对象(或完全是其他东西)?的主要内容,如果未能解决你的问题,请参考以下文章