为什么没有java.lang.Array类?如果Java数组是一个对象,它不应该扩展Object吗?

46

这里是Java的包树结构: http://docs.oracle.com/javase/7/docs/api/java/lang/package-tree.html

我读过一篇Java教程,它说Java中数组是对象。

那么数组类在哪里?我们怎么能像这样创建数组:

byte[] byteArr = new byte[];
char[] charArr = new char[];
int[] intArr = new int[];

数组将继承Object的方法;例如:

    byte thisByte = 1;
    byte thatByte = 2;
    byte[] theseBytes = new byte[] {thisByte, thatByte};
    int inheritance = theseBytes.length; //inherited 'length' field and some methods
    int wasntInWill = thatByte.length; //error

这里发生了什么?

编辑:

根据答案,我现在知道它是java.lang.reflect包中的一个final类。

我现在在我的Android项目中创建了一个名为Array.java的类,并将其添加到java.lang.reflect包中。为了确认这是原始类的方法,Eclipse给出了错误“...已经存在于path/to/android.jar”

如果我将同样的类写成java.lang.reflect.Array,但更改toString()方法... 这应该在我的应用程序中起作用,对吗?


数组是对象,但其构造语法与通常的Java对象略有不同。 - Op De Cirkel
1
不对。它不是在java.lang.reflect包中的“final”类。 - user207421
4个回答

49

来自JLS:

每个数组都有一个关联的Class对象,与所有具有相同组件类型的其他数组共享。[这]就像:数组类型的直接超类是Object,并且每个数组类型都实现了Cloneable和java.io.Serializable接口。

以下示例代码说明了这一点:

class Test {
    public static void main(String[] args) {
        int[] ia = new int[3];
        System.out.println(ia.getClass());
        System.out.println(ia.getClass().getSuperclass());
    }
}

输出结果为:

class [I
class java.lang.Object

"[I"是表示类型为"int" 的数组类对象的运行时类型签名。

因为数组类型本质上扩展了Object,所以您可以在arrayObject上调用toString(),请参见上面的示例。

int arr[] = new arr[2];
arr.toString();

嗨,谢谢提供信息。我编辑了我的问题,以便更好地表达我的真正需求——如何覆盖数组的toString()方法。 - Ozzy
欢迎,如果你手头没有类可以更改,最好创建一个实用方法,接受数组对象并以你想要的形式打印它。 - jmj
我知道,我只是想看看它是否能够完成。当然,在我问之前应该先尝试一下,但是在我内心深处,还有一个小白的部分担心这会使我的电脑崩溃! - Ozzy
1
对于toString(),只需使用Arryas.asList()。 - Thorbjørn Ravn Andersen
我也知道这个,但还是谢谢。我想看看是否可以通过编写toString()方法来使我的数组正常工作。 - Ozzy
@JigarJoshi:我不明白[I类是如何创建的,以及为什么只有变量length用于数组?此外,当我在运行时使用System.out.println(arr.length);时,为什么编译器不会显示错误,因为数组对象是在运行时创建的? - Mohammad Faisal

10

数组是一种语言特性 - 它们有特定的声明和访问语法。而它们的类定义对你来说是隐藏的。

它们在反射 API 中有一个表示方式 - java.lang.reflect.Array

顺便提一下,length 字段不是从 Object 继承而来的。而 .getClass().toString() 等方法是继承而来的。


哦,java.lang.reflect.Array是类定义?是的,我是指从某个数组对象继承(以证明有一个数组类存在)。 - Ozzy
1
length字段不存在,任何数组中都没有这样的字段。它只是Java语言特性,代表ARRAYLENGTH操作码类似的字段。从技术上讲,几乎每个实现都在对象头中有这样的字段。数组还实现了2个接口:SerializableClonable并公开clone()方法。 - bestsss
3
不,java.lang.reflect.Array不是类定义。它是一个仅包含静态方法的实用反射类。 - user207421
6
@Bozho 有没有修复这个答案的计划?你已经有4.5年的时间了。 - user207421
2
只是为了给后来者更清晰的认识。如果你执行 Integer[] array = new Integer[0]; System.out.println(array.getClass());,你应该看到类是 class [Ljava.lang.String;,而不是 java.lang.reflect.Array - somenickname

7
以上代码段的稍微详细解释如下:
public class ClassForName {
    public static void main(String[] argv) throws ClassNotFoundException {
        Class theClass = Class.forName("[I");
        System.out.println(theClass.getName());
        Class superClass = theClass.getSuperclass();
        System.out.println(superClass.getName());
    }
}

结果:

C:\JavaTools>java ClassForName
[I
java.lang.Object

可以看到,"[I"是我们在英语中称为"array of int"的类的名称。该类是一个完全具有Java公民身份的类,可以响应Object的所有方法。唯一的区别是new语法不同,并且不支持Class的newInstance()方法。
(类"[I"、"[C"等都是JVM中预定义的,没有相应的.class文件。如果程序中有"MyJavaClass"数组,则Java也会自动创建"[MyJavaClass;"类。)

1
大部分是正确的,但是:1.更进一步的区别在于类既是Cloneable又是Serializable。2.JLSJVM规范都指出所有数组类都是动态创建的。没有关于其中一些内置的内容。 - user207421

4
为什么没有数组类?
每个程序使用的元素类型都有一个数组类。Java语言规范和JVM规范都明确说明,数组的类对象是动态创建的。JLS #10.8 'Class Objects for Arrays'JVM Spec #5.3.3 'Creating Array Classes'
如果Java数组是一个对象,那它不应该扩展Object吗?
它确实扩展了java.lang.Object。JLS #10.8清楚地说明“每个数组类型的直接超类是Object”。

你有点晚了,我已经找到那个类了(请看上面的答案)。 - Ozzy
@Ozzy,你在任何地方都没有找到这个类。它没有被定义在任何地方。它甚至不是一个单独的类。对于每种原始类型,例如int[],都有一个类,对于每种对象类型,例如Object[]String[]等,也都有一个类。 - user207421
在JLS 10.8中,它说“数组类型不是类”。那么动态创建的类算不算类呢? - csguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接