com Java5, podemos escrever:
Foo[] foos = ...
for (Foo foo : foos)
ou apenas usando um Iterable no loop for. Isso é muito útil.
No entanto, você não pode escrever um método genérico para iterável como este:
public void bar(Iterable<Foo> foos) { .. }
e chamando-o com uma matriz, pois não é um Iterable:
Foo[] foos = { .. };
bar(foos); // compile time error
Estou pensando nas razões por trás dessa decisão de design.
java
language-design
dfa
fonte
fonte
java.lang.reflect.Array
, mas seu desempenho é fraco. No entanto, você pode escrever seus próprios iteradores (ou implementações de lista!) Para agrupar matrizes de tipos primitivos, se desejar.Respostas:
Matrizes podem implementar interfaces (
Cloneable
ejava.io.Serializable
). Então porque nãoIterable
? Eu acho queIterable
forças adicionando umiterator
método, e matrizes não implementam métodos.char[]
nem substituitoString
. De qualquer forma, as matrizes de referências devem ser consideradas abaixo do ideal - useList
s. Como comentários do dfa,Arrays.asList
fará a conversão explicitamente.(Dito isso, você pode chamar
clone
matrizes.)fonte
Iterator<T>
também requerremove(T)
, embora seja permitido lançar umUnsupportedOperationException
.java.lang.Object
.A matriz é um objeto, mas seus itens podem não ser. A matriz pode conter um tipo primitivo como int, que o Iterable não pode lidar. Pelo menos é o que eu acho.
fonte
Iterable
interface, as matrizes primitivas devem ser especializadas para usar as classes de wrapper. Porém, nada disso é realmente importante, já que os parâmetros de tipo são todos falsos.List<int>
vez deList<Integer>
etc). A corte poderia ser feito com wrappers, mas com perda de performance - e mais importante - se este hack foi feito, it'ld evitar implementá-lo corretamente em Java no futuro (por exemplo,int[].iterator()
seria para sempre ser bloqueado para retornarIterator<Integer>
ao invésIterator<int>
). Talvez, os próximos tipos de valor + especialização genérica para Java (projeto valhalla) tornem as matrizes implementadasIterable
.As matrizes devem suportar
Iterable
, simplesmente não, pelo mesmo motivo que as matrizes .NET não suportam uma interface que permite acesso aleatório somente leitura por posição (não existe uma interface definida como padrão). Basicamente, as estruturas costumam ter pequenas lacunas irritantes, o que não vale a pena reparar. Não importaria se poderíamos corrigi-los da melhor maneira possível, mas geralmente não podemos.ATUALIZAÇÃO: Para ser imparcial, mencionei matrizes .NET que não suportam uma interface que suporta acesso aleatório por posição (consulte também meu comentário). Mas no .NET 4.5 essa interface exata foi definida e é suportada por matrizes e pela
List<T>
classe:Tudo ainda não é perfeito porque a interface da lista mutável
IList<T>
não herdaIReadOnlyList<T>
:Talvez exista uma possível compatibilidade com essa alteração.
Se houver algum progresso em coisas semelhantes nas versões mais recentes do Java, eu estaria interessado em saber nos comentários! :)
fonte
IList<T>
expõe operações para modificação. Seria ótimo seIList<T>
tinha herdado algo como umaIReadonlyList<T>
interface, que teria apenas tinhaCount
eT this[int]
e herdouIEnumerable<T>
(que já suporta enumeração somente leitura). Outro grande coisa seria uma interface para a obtenção de um recenseador-ordem inversa, que oReverse
método de extensão pode consultar (assim como asCount
consultas de método de extensão paraICollection
otimizar si mesmo.)IList
eICollection
desde o .NET 1.1IList<T>
eICollection<T>
desde o .NET 2.0. Esse é outro caso em que o Java está muito atrás da concorrência.IList
é que ele não fornece mais atributos consultáveis. Eu diria que um conjunto adequado deve incluir IsUpdateable, IsResizable, IsReadOnly, IsFixedSize e ExistingElementsAreImmutable para iniciantes. A questão de saber se o código que uma referência pode, sem conversão de tipo, modificar uma lista é separada das questões sobre se o código que contém uma referência a uma lista que não deveria modificar pode compartilhar com segurança essa referência diretamente com o código externo ou se pode assumir com segurança que algum aspecto da lista nunca será alterado.Infelizmente, matrizes não são '
class
suficientes'. Eles não implementam aIterable
interface.Enquanto matrizes agora são objetos que implementam Clonable e Serializable, acredito que uma matriz não é um objeto no sentido normal e não implementa a interface.
A razão pela qual você pode usá-los em cada loop é porque a Sun adicionou um pouco de açúcar sintático para matrizes (é um caso especial).
Como as matrizes começaram como 'quase objetos' no Java 1, seria uma mudança drástica demais para torná-las objetos reais em Java.
fonte
Cloneable
eSerializable
interfaces.O compilador na verdade converte o
for each
em uma matriz em umfor
loop simples com uma variável de contador.Compilando o seguinte
e, em seguida, descompilar o arquivo .class gera
fonte