Java 为什么数组不能分配给 Iterable?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1160081/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:23:25  来源:igfitidea点击:

Why is an array not assignable to Iterable?

javalanguage-design

提问by dfa

with Java5 we can write:

使用 Java5 我们可以这样写:

Foo[] foos = ...
for (Foo foo : foos) 

or just using an Iterable in the for loop. This is very handy.

或者只是在 for 循环中使用 Iterable 。这非常方便。

However you can't write a generic method for iterable like this:

但是,您不能像这样为可迭代编写通用方法:

public void bar(Iterable<Foo> foos) { .. }

and calling it with an array since it is not an Iterable:

并使用数组调用它,因为它不是可迭代的:

Foo[] foos = { .. };
bar(foos);  // compile time error 

I'm wondering about the reasons behind this design decision.

我想知道这个设计决定背后的原因。

采纳答案by Tom Hawtin - tackline

Arrays can implement interfaces (Cloneableand java.io.Serializable). So why not Iterable? I guess Iterableforces adding an iteratormethod, and arrays don't implement methods. char[]doesn't even override toString. Anyway, arrays of references should be considered less than ideal - use Lists. As dfa comments, Arrays.asListwill do the conversion for you, explicitly.

数组可以实现接口(Cloneablejava.io.Serializable)。那么为什么不Iterable呢?我想Iterable强制添加一个iterator方法,而数组不实现方法。char[]甚至不覆盖toString. 无论如何,引用数组应该被认为不太理想 - 使用Lists。正如 dfa 评论的那样,Arrays.asList将明确地为您进行转换。

(Having said that, you can call cloneon arrays.)

(话虽如此,您可以调用clone数组。)

回答by jjnguy

Unfortunately, arrays aren't 'class-enough'. They don't implement the Iterableinterface.

不幸的是,数组不是“class足够的”。他们不实现Iterable接口。

While arrays are now objects that implement Clonable and Serializable, I believe an array isn't an object in the normal sense, and doesn't implement the interface.

虽然数组现在是实现了 Clonable 和 Serializable 的对象,但我相信数组不是正常意义上的对象,也没有实现接口。

The reason you can use them in for-each loops is because Sun added in some syntatic sugar for arrays (it's a special case).

您可以在 for-each 循环中使用它们的原因是 Sun 为数组添加了一些语法糖(这是一种特殊情况)。

Since arrays started out as 'almost objects' with Java 1, it would be far too drastic of a change to make them realobjects in Java.

由于数组在 Java 1 中是作为“几乎对象”开始的,因此在 Java中使它们成为真正的对象将是非常剧烈的变化。

回答by Daniel Earwicker

Arrays ought to support Iterable, they just don't, for the same reason that .NET arrays don't support an interface that allows readonly random access by position (there is no such interface defined as standard). Basically, frameworks often have annoying little gaps in them, which it's not worth anyone's time to fix. It wouldn't matter if we could fix them ourselves in some optimal way, but often we can't.

数组应该支持Iterable,他们只是不支持,原因与 .NET 数组不支持允许按位置进行只读随机访问的接口相同(没有这样的接口定义为标准)。基本上,框架中通常有令人讨厌的小漏洞,不值得任何人花时间来修复。如果我们能以某种最佳方式自己修复它们并不重要,但通常我们不能。

UPDATE:To be even-handed, I mentioned .NET arrays not supporting an interface that supports random access by position (see also my comment). But in .NET 4.5 that exact interface has been defined and is supported by arrays and the List<T>class:

更新:为了公平起见,我提到 .NET 数组不支持支持按位置随机访问的接口(另请参阅我的评论)。但是在 .NET 4.5 中,已经定义了确切的接口,并由数组和List<T>类支持:

IReadOnlyList<int> a = new[] {1, 2, 3, 4};
IReadOnlyList<int> b = new List<int> { 1, 2, 3, 4 };

All is still not quite perfect because the mutable list interface IList<T>doesn't inherit IReadOnlyList<T>:

All 仍然不是很完美,因为可变列表接口IList<T>没有继承IReadOnlyList<T>

IList<int> c = new List<int> { 1, 2, 3, 4 };
IReadOnlyList<int> d = c; // error

Maybe there is a possible backward compatibility gotcha with such a change.

也许这种更改可能存在向后兼容性问题。

If there's any progress on similar things in newer versions of Java, I'd be interested to know in the comments! :)

如果在较新版本的 Java 中在类似的事情上有任何进展,我很想在评论中知道!:)

回答by Gareth Adamson

The array is an Object, but its items might not be. The array might hold a primitive type like int, which Iterable can't cope with. At least that's what I reckon.

该数组是一个对象,但它的项目可能不是。该数组可能包含像 int 这样的原始类型,这是 Iterable 无法处理的。至少我是这么认为的。

回答by das Keks

The compiler actually translates the for eachon an array into a simple forloop with a counter variable.

编译器实际上将for each数组上的 转换为for带有计数器变量的简单循环。

Compiling the following

编译如下

public void doArrayForEach() {
    int[] ints = new int[5];

    for(int i : ints) {
        System.out.println(i);
    }
}

and then decompiling the .class file yields

然后反编译 .class 文件产生

public void doArrayForEach() {
    int[] ints = new int[5];
    int[] var2 = ints;
    int var3 = ints.length;

    for(int var4 = 0; var4 < var3; ++var4) {
        int i = var2[var4];
        System.out.println(i);
    }
}