с Java5 мы можем написать:
Foo[] foos = ...
for (Foo foo : foos)
или просто используя Iterable в цикле for. Это очень удобно.
Однако вы не можете написать универсальный метод для повторяемого, как это:
public void bar(Iterable<Foo> foos) { .. }
и вызывая его с массивом, поскольку он не является Iterable:
Foo[] foos = { .. };
bar(foos); // compile time error
Я задаюсь вопросом о причинах этого дизайнерского решения.
java.lang.reflect.Array
, но его производительность слабая. Однако вы можете написать свои собственные итераторы (или реализации List!), Чтобы обернуть массивы примитивных типов, если хотите.Ответы:
Массивы могут реализовывать интерфейсы (
Cloneable
иjava.io.Serializable
). Так почему бы и нетIterable
? Я предполагаю, чтоIterable
силы добавляютiterator
метод, а массивы не реализуют методы.char[]
даже не переопределитьtoString
. В любом случае, массивы ссылок следует считать не идеальными - используйтеList
s. Как комментирует dfa,Arrays.asList
мы сделаем конвертацию за вас.(Сказав это, вы можете вызвать
clone
массивы.)источник
Iterator<T>
также требуетremove(T)
, хотя это разрешено бросатьUnsupportedOperationException
.java.lang.Object
.Массив является объектом, но его элементы могут не быть. Массив может содержать тип примитива типа int, с которым Iterable не может справиться. По крайней мере, это то, что я считаю.
источник
Iterable
интерфейса примитивные массивы должны быть специализированы для использования классов-оболочек. Ничего из этого не имеет большого значения, поскольку параметры типа все равно являются фальшивыми.List<int>
вместоList<Integer>
и т. Д.). Взлом может быть осуществлен с помощью упаковщиков, но с потерей производительности - и что еще более важно - если этот взлом будет осуществлен, это предотвратит его надлежащую реализацию в Java в будущем (напримерint[].iterator()
, навсегда будет заблокировано для возврата,Iterator<Integer>
а неIterator<int>
). Возможно, грядущие значения-типы + обобщенная специализация для Java (проект valhalla) заставят массивы реализоватьIterable
.Массивы должны поддерживать
Iterable
, они просто не поддерживают , по той же причине, по которой массивы .NET не поддерживают интерфейс, который обеспечивает произвольный доступ только для чтения по позиции (такой интерфейс не определен как стандартный). По сути, фреймворки часто имеют в себе небольшие пробелы, которые никому не стоит исправлять. Не имело бы значения, если бы мы могли исправить их самостоятельно каким-то оптимальным способом, но часто мы не можем.ОБНОВЛЕНИЕ: Чтобы быть беспристрастным, я упомянул массивы .NET, не поддерживающие интерфейс, который поддерживает произвольный доступ по позиции (см. Также мой комментарий). Но в .NET 4.5 этот точный интерфейс был определен и поддерживается массивами и
List<T>
классом:Все еще не совсем идеально, потому что интерфейс изменяемого списка
IList<T>
не наследуетIReadOnlyList<T>
:Может быть, есть вероятность обратной совместимости с таким изменением.
Если есть какие-то успехи в подобных вещах в новых версиях Java, мне было бы интересно узнать в комментариях! :)
источник
IList<T>
выставляет операции для модификации. Было бы замечательно, еслиIList<T>
бы унаследовал что-то вродеIReadonlyList<T>
интерфейса, который бы только что имелCount
иT this[int]
и унаследовалIEnumerable<T>
(который уже поддерживает перечисление только для чтения). Еще одна интересная вещь - это интерфейс для получения перечислителя обратного порядка, к которому может обращатьсяReverse
метод расширения (так же, какCount
метод расширения запрашивает дляICollection
оптимизации).IList
иICollection
с .NET 1.1,IList<T>
иICollection<T>
с .NET 2.0. Это еще один случай, когда Java сильно отстает от конкурентов.IList
том, что он не предоставляет больше запрашиваемых атрибутов. Я бы сказал, что правильный набор должен включать IsUpdateable, IsResizable, IsReadOnly, IsFixedSize и ExistingElementsAreImmutable для начинающих. Вопрос о том, может ли ссылка, на которую ссылается код, изменять тип без изменения типа, отдельно от вопросов о том, может ли код, содержащий ссылку на список, который он не должен изменять, безопасно делиться этой ссылкой напрямую с внешним кодом или можно смело предположить, что какой-то аспект списка никогда не изменится.К сожалению, массивов не
class
достаточно. Они не реализуютIterable
интерфейс.Хотя массивы теперь являются объектами, которые реализуют Clonable и Serializable, я считаю, что массив не является объектом в обычном смысле и не реализует интерфейс.
Причина, по которой вы можете использовать их в циклах for-each, заключается в том, что Sun добавила синтетический сахар для массивов (это особый случай).
Так как массивы начинались как «почти объекты» в Java 1, было бы слишком радикально изменить их, чтобы сделать их реальными объектами в Java.
источник
Cloneable
иSerializable
интерфейсы.Компилятор фактически переводит
for each
массив в простойfor
цикл с переменной счетчика.Составление следующего
а затем декомпиляция файла .class дает
источник