在Java语言和数组的JVM中有一堆特殊情况。数组有一个 API,但它几乎不可见。就好像数组被声明为具有:
implements Cloneable, Serializable
public final int length
-
public T[] clone()
其中 是数组的组件类型T
但是,这些声明在任何位置的任何源代码中都不可见。有关说明,请参阅 JLS 4.10.3 和 JLS 10.7。 并通过反射可见,并通过调用返回Cloneable
Serializable
Object[].class.getInterfaces()
也许令人惊讶的是,场和方法在反射上是不可见的。该字段根本不是字段;使用它会变成一个特殊的字节码。对的调用会导致实际的虚拟方法调用,但如果接收方是数组类型,则 JVM 会特别处理此调用。length
clone()
length
arraylength
clone()
但是,值得注意的是,数组类不实现该接口。Iterable
当在 Java SE 5 中添加增强型 for 循环(“for-each”)时,它支持右侧表达式的两种不同情况:一种或一种数组类型 (JLS 14.14.2)。原因是实例和数组的处理方式与增强型语句完全不同。JLS的该部分给出了完整的处理,但更简单地说,情况如下。Iterable
Iterable
对于 ,代码Iterable<T> iterable
for (T t : iterable) {
<loop body>
}
是句法糖
for (Iterator<T> iterator = iterable.iterator(); iterator.hasNext(); ) {
t = iterator.next();
<loop body>
}
对于数组,代码T[]
for (T t : array) {
<loop body>
}
是句法糖
int len = array.length;
for (int i = 0; i < len; i++) {
t = array[i];
<loop body>
}
那么,为什么会这样完成呢?数组当然有可能实现,因为它们已经实现了其他接口。编译器还可以合成由数组支持的实现。(这是有先例的。编译器已经合成了自动添加到每个类的静态和方法,如 JLS 8.9.3 中所述。Iterable
Iterator
values()
valueOf()
enum
但是数组是一种非常低级的结构,通过值访问数组应该是非常便宜的操作。将循环索引从运行到数组的长度是非常惯用的,每次递增一。数组上的增强型 for 循环正是这样做的。如果数组上的增强型循环是使用该协议实现的,我想大多数人都会不愉快地惊讶地发现,循环访问数组涉及初始方法调用和内存分配(创建),然后每次循环迭代两次方法调用。int
0
Iterable
Iterator
因此,当在Java 8中添加默认方法时,这根本不会影响数组。Iterable
正如其他人所指出的,如果您有一个 、 、 或引用类型的数组,则可以使用其中一个调用将其转换为流。这提供了对 、 、 等 的访问。int
long
double
Arrays.stream()
map()
filter()
forEach()
不过,如果 Java 语言和数组 JVM 中的特殊情况被真正的构造所取代(同时修复一堆其他与数组相关的问题,例如 2+ 维数组的处理不当、2^31 的长度限制等),那就太好了。这是John Rose领导的“Arrays 2.0”调查的主题。参见 John 在 JVMLS 2012 上的演讲(视频、幻灯片)。与此讨论相关的想法包括引入数组的实际接口,以允许库插入元素访问,支持其他操作,如切片和复制等。
请注意,所有这些都是调查和未来的工作。在撰写本文时(2016-02-23),这些数组增强功能在Java路线图中都没有提交任何版本。