问题描述
Java 语言规范says:
还有says:
数组 [...] 可以分配给 Object 类型的变量
但是 the part that confuses me 是:
Object 类是所有其他类的超类
如果数组可以分配给对象类型的变量,那么它必须意味着数组可以是对象(不仅行为,而是成为)。那么就说明一个数组是一个类实例,这似乎和第一个引用不一致(如果是,那为什么会被列为不同的东西?)。
如何将所有这些组合在一起?
解决方法
没有矛盾。
数组也是对象,尽管是一种特殊的对象。
就像在说:鸟也是动物,虽然是一种特殊的动物。
您可以通过编译和运行以下 Java 代码来说服自己。
String[] arrayOfStrings = { "bla","blah" };
// examine the class hierarchy of the array
System.out.println("arrayOfStrings is of type "
+ arrayOfStrings.getClass().getSimpleName()
+ " which extends from "
+ arrayOfStrings.getClass().getSuperclass().getSimpleName());
// assingning the array to a variable of type Object
Object object = arrayOfStrings;
输出将是
arrayOfStrings is of type String[] which extends from Object
,
数组是 Java 本身提供给您的特殊类。它们都继承自通用超类 Object
。由于它们继承自 Object
,它们当然可以在需要 Object
的任何地方使用。数组的实例确实是这些类的实例。甚至可以像引用其他类的文字一样引用数组类:
Class<int[]> intArrayClass = int[].class;
我认为没有冲突。
这很有用https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#jls-10.8
,Object 类是所有其他类的超类
Java 中的所有类都扩展了对象。类名实际上是 Object(专有名称大写)。这就是为什么所有类都有 toString() 和 hashCode() 方法的原因,因为它们都继承自 Object.class
一个对象是一个类实例或一个数组。
一个对象(小写,不是专有名称)是由 new 关键字生成的实例。即: File 是一个类,当您调用 new File() 时,您只是创建了一个 File 对象。老实说,我认为他们应该将其称为类实例。 (澄清:我希望他们永远不会将实例称为对象)
数组 [...] 可以分配给 Object 类型的变量
Object[] 是一个可以包含 Object 类型实例的数组。
Object[] obj = new Object[100];
obj instanceof Object
的计算结果为 true。
您的 second link 还说:
Object 类的所有方法都可以在数组上调用。
因此,至少从开发人员的 POV 来看,它是一个 Object
,尽管它没有实例化的 java.lang.Array
(暴露给我们)。
第二个迹象是数组也存储在堆上。
,是的……也不是。确实,new Object[100] instanceof Object
→ true
确实如此,但这缺少 Java 中数组的真正性质。数组是对象(小写),但不是对象(大写)。例如,作为对象,您必须使用 new
运算符为它们分配空间。
然而,Java 语言规范说“一个对象是一个类实例或一个数组”是正确的,因为数组从根本上不同于常规对象。它们继承自 C++ 等语言,这些语言更深地植根于计算机的低级架构。
“数组 [...] 可以分配给 Object 类型的变量” 只是因为 Java 为我们程序员提供了一个接口,将数组称为对象.事实上,JLS says:
Object 类的所有方法都可以在数组上调用
这当然是对的,但在逻辑上并不意味着它们是对象。数组不是真正的对象;因此,它们不是真正的类实例,因此句子“类对象是所有其他类的超类”在这里不适用。
总而言之,Java 不是纯粹的面向对象的编程语言(例如,原语不是对象,但它们仍然存在于 Java 中)。而数组是Java包含的一种语言特性,行为就像 Object类的类实例,但实际上不是它的类实例.
[这是我试图总结这里提出的要点。非常感谢你们所有人的想法,并随时添加更多!]