con Java5 podemos escribir:
Foo[] foos = ...
for (Foo foo : foos)
o simplemente usando un Iterable en el ciclo for. Esto es muy útil.
Sin embargo, no puede escribir un método genérico para iterable como este:
public void bar(Iterable<Foo> foos) { .. }
y llamarlo con una matriz ya que no es un Iterable:
Foo[] foos = { .. };
bar(foos); // compile time error
Me pregunto las razones detrás de esta decisión de diseño.
java.lang.reflect.Array
, pero su rendimiento es débil. Sin embargo, puede escribir sus propios iteradores (¡o listar implementaciones!) Para envolver matrices de tipos primitivos si lo desea.Respuestas:
Las matrices pueden implementar interfaces (
Cloneable
yjava.io.Serializable
). Entonces, ¿por qué noIterable
? Supongo queIterable
obliga a agregar uniterator
método, y las matrices no implementan métodos.char[]
Ni siquiera anulatoString
. De todos modos, los conjuntos de referencias deben considerarse menos que ideales: useList
s. Como comenta dfa,Arrays.asList
hará la conversión por usted, explícitamente.(Dicho esto, puede llamar
clone
a las matrices).fuente
Iterator<T>
también requiereremove(T)
, aunque está permitido lanzar unUnsupportedOperationException
.java.lang.Object
.La matriz es un objeto, pero sus elementos pueden no serlo. La matriz puede contener un tipo primitivo como int, que Iterable no puede hacer frente. Al menos eso creo.
fuente
Iterable
interfaz, las matrices primitivas deben estar especializadas para usar las clases envolventes. Sin embargo, nada de esto es realmente un gran problema, ya que los parámetros de tipo son todos falsos de todos modos.List<int>
lugar deList<Integer>
, etc.). Se podría realizar un hack con envoltorios pero con una pérdida de rendimiento, y lo que es más importante, si se realizara este truco, evitaría implementarlo correctamente en Java en el futuro (por ejemploint[].iterator()
, se bloquearía para siempre enIterator<Integer>
lugar de hacerloIterator<int>
). Quizás, los próximos tipos de valor + especialización genérica para Java (proyecto valhalla) harán que las matrices se implementenIterable
.Las matrices deberían admitir
Iterable
, simplemente no lo hacen, por la misma razón que las matrices .NET no admiten una interfaz que permita el acceso aleatorio de solo lectura por posición (no existe una interfaz definida como estándar). Básicamente, los marcos a menudo tienen pequeñas brechas molestas, que no vale la pena el tiempo de arreglar. No importaría si pudiéramos arreglarlos nosotros mismos de una manera óptima, pero a menudo no podemos.ACTUALIZACIÓN: Para ser imparcial, mencioné que las matrices .NET no admiten una interfaz que admita el acceso aleatorio por posición (ver también mi comentario). Pero en .NET 4.5 esa interfaz exacta se ha definido y es compatible con las matrices y el
List<T>
clase:Todo aún no es perfecto porque la interfaz de lista mutable
IList<T>
no heredaIReadOnlyList<T>
:Tal vez hay un posible problema de compatibilidad con versiones anteriores con tal cambio.
Si hay algún progreso en cosas similares en las versiones más recientes de Java, ¡me interesaría saber en los comentarios! :)
fuente
IList<T>
expone operaciones para modificar. Sería muy bueno siIList<T>
había heredado algo así como unaIReadonlyList<T>
interfaz, lo que habría tenido soloCount
yT this[int]
e heredadaIEnumerable<T>
(que ya soporta la enumeración de sólo lectura). Otra gran cosa sería una interfaz para obtener un enumerador de orden inverso, que elReverse
método de extensión podría consultar (al igual que elCount
método de extensión buscaICollection
optimizarse)IList
&ICollection
desde .NET 1.1,IList<T>
yICollection<T>
desde .NET 2.0. Este es otro caso en el que Java está muy por detrás de la competencia.IList
es que no proporciona más atributos consultables. Yo diría que un conjunto adecuado debería incluir IsUpdateable, IsResizable, IsReadOnly, IsFixedSize y ExistingElementsAreImmutable para empezar. La cuestión de si el código de una referencia puede, sin encasillamiento, modificar una lista es independiente de las preguntas de si el código que contiene una referencia a una lista que no debe modificar puede compartir esa referencia directamente con el código externo, o si puede asumir con seguridad que algún aspecto de la lista nunca cambiará.Desafortunadamente, las matrices no son "
class
suficientes". No implementan elIterable
interfaz.Si bien las matrices ahora son objetos que implementan Clonable y Serializable, creo que una matriz no es un objeto en el sentido normal , y no implementa la interfaz.
La razón por la que puede usarlos en los bucles for-each es porque Sun agregó algo de azúcar sintético para los arrays (es un caso especial).
Dado que las matrices comenzaron como 'casi objetos' con Java 1, sería un cambio demasiado drástico hacerlos objetos reales en Java.
fuente
Cloneable
eSerializable
interfaces.El compilador en realidad traduce el
for each
en una matriz en unfor
bucle simple con una variable de contador.Compilando lo siguiente
y luego descompilando el archivo .class produce
fuente