Почему массив не присваивается Iterable?

с Java5 мы можем написать:

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

или просто используя Iterable в цикле for. Это очень удобно.

Однако вы не можете написать общий метод для итерации следующим образом:

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

и вызывая его с массивом, поскольку он не является Итерируемым:

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

Мне интересно узнать причины этого решения.

Ответ 1

Массивы могут реализовывать интерфейсы (Cloneable и java.io.Serializable). Так почему бы не Iterable? Я полагаю, что Iterable принудительно добавляет метод iterator, а массивы не реализуют методы. char[] даже не отменяет toString. Во всяком случае, массивы ссылок следует считать менее идеальными - используйте List s. Как комментарии dfa, Arrays.asList сделает для вас преобразование явно.

(Сказав это, вы можете вызвать clone на массивы.)

Ответ 2

Массив - это объект, но его элементы могут быть не такими. Массив может содержать примитивный тип типа int, с которым Iterable не справляется. По крайней мере, это то, что я считаю.

Ответ 3

Массивы должны поддерживать Iterable, они просто этого не делают, по той же причине, что .NET-массивы не поддерживают интерфейс, который позволяет выполнять только произвольный доступ по позиции (только такой интерфейс не определен как стандартный). По сути, в структурах часто есть раздражающие небольшие пробелы в них, что не стоит никого времени исправить. Не имело бы значения, можем ли мы исправить их самим каким-то оптимальным способом, но часто мы не можем.

UPDATE: Чтобы быть беспристрастным, я упомянул .NET-массивы, не поддерживающие интерфейс, поддерживающий произвольный доступ по позиции (см. также мой комментарий). Но в .NET 4.5 этот точный интерфейс был определен и поддерживается массивами и классом List<T>:

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

Все еще не совсем идеально, потому что измененный интерфейс списка IList<T> не наследует IReadOnlyList<T>:

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

Возможно, есть возможная возможность обратной совместимости с таким изменением.

Если в новых версиях Java есть какой-то прогресс в аналогичных вещах, мне было бы интересно узнать в комментариях!:)

Ответ 4

К сожалению, массивы не 'class -enough'. Они не реализуют интерфейс Iterable.

Пока массивы теперь являются объектами, реализующими Clonable и Serializable, я считаю, что массив не является объектом в обычном смысле и не реализует интерфейс.

Причина, по которой вы можете использовать их для каждого цикла, заключается в том, что Sun добавлено в некоторый синтаксический сахар для массивов (это особый случай).

Поскольку массивы начинались как "почти объекты" с Java 1, это было бы слишком радикально для изменения, чтобы сделать их реальными объектами в Java.