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