1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

JAVA: Criação de Array Genérico

Discussão em 'Programação' iniciada por IcePicK, 12 de Dezembro de 2008. (Respostas: 9; Visualizações: 2572)

  1. IcePicK

    IcePicK Power Member

    Uma das questões mais pertinentes em relação aos tipos genéricos do Java é a criação de arrays.

    Por exemplo, como criar um array "nativo" partindo de uma colecção?

    Código:
    public static <T> T[] toArray(final Collection<T> c);
    Uma das implementações possiveis deste método é:

    Código:
    public static <T> T[] toArray(final Collection<T> c) {
    	return c.toArray((T[]) Array.newInstance(c.iterator().next().getClass(), 0));
    }
    Mas este método só funciona se:
    • c tem pelo menos um elemento
    • o primeiro elemento de c é mesmo do tipo T e não um sub-tipo

    Quais as vossas soluções para este problema?
     
  2. solidforms

    solidforms Power Member

    O que queres dizer com sub-tipos? Quando crias uma classe genérica <T> ou <K,V> tens que assumir que todos os dados são tratados uniformemente. Se posteriormente usares essa estrutura para Strings, para as funções funcionarem convenientemente devem usar o mesmos tipos. Logo, penso que não existem soluções para esse problema. Tens que tratar todos os tipos de dados como <T>.

    Nao percebi bem a duvida, portanto, espero ter ajudado.

    Cumps ;).
     
  3. IComeFromBehind

    IComeFromBehind Power Member

    eu uso c.toArray(new <Tipo do C>[c.size()])
     
  4. IcePicK

    IcePicK Power Member

    Quando digo que não pode ser um sub-tipo é porque esta implementação utiliza o primeiro elemento para obter o tipo para o novo array (c.iterator().next().getClass()). Portanto, se o primero elemento for X (sub-tipo de T) vai ser criado um X[] resultando mais tarde numa ClassCastException.

    Pois, eu também faço assim quando sei o tipo. Aqui não sabemos o tipo.

    Uma solução possivel mas menos transparente era:

    Código:
    public static <T> T[] toArray(final Collection<T> c, Class<T[]> clazz) {
    	return c.toArray((T[]) Array.newInstance(clazz, 0));
    }
    No entanto fica menos "elegante" para os clientes.
     
  5. IComeFromBehind

    IComeFromBehind Power Member

    E que tal percorrer todos os elementos e verificar qual o que tem a hierarquia mais elevada? Se a colecção tiver dimensão zero retornas Objecto. Sinceramente parece-me muito esforço para nada.

    Edit: Mas estás a tentar resolver algum problema concreto? Se não sabes os tipos de objectos da colecção depois de converteres para array continuas sem saber os tipos em tempo de compilação dai eu não perceber qual o objectivo.
     
    Última edição: 12 de Dezembro de 2008
  6. IcePicK

    IcePicK Power Member

    Sim, estou a resolver um problema em concreto e que nem conseguia explicar aqui.

    As classes clientes sabem quais os tipos com que estão a trabalhar. Só queria fazer as coisas transparentes para os clientes.

    Entretanto já resolvi o problema para este caso em especifico ficando a questão geral em aberto.
     
  7. IComeFromBehind

    IComeFromBehind Power Member

    Código:
    public static <T> T[] toArray(final Collection<T> c) {
    	return c.toArray((T[]) new Object[c.size()]);
    }
    
     
  8. IcePicK

    IcePicK Power Member

    Se fizeres...
    Código:
    ArrayList<String> s = new ArrayList<String>();
    
    String [] a = toArray(s);
    
    com a tua implementação vai dar uma ClassCastException pois estas a fazer um cast implícito de Object[] para String[].
     
  9. IComeFromBehind

    IComeFromBehind Power Member

    Passado tanto tempo depois de ter tentado contornar o erasure das mais diversas maneiras, esta thread vem-me lembrar o porquê de ter parado. Devia ter aprendido a lição melhor.
     
  10. AliFromCairo

    AliFromCairo Power Member

    Sim, aquele cast não faz qualquer tipo de sentido. De qualquer forma, arrays e tipos genéricos não combinam muito bem. Provavelmente, é algo que deverá ser melhorado na próxima versão do Java. Aliás, basta pesquisar por "java erase erasure" no Google, que aparecem bastantes resultados.

    Para concluir, já aqui colocaste várias possíveis soluções para o problema; poderão não ser as mais elegantes, mas isto é uma "limitação" do Java e, como tal, não tens grandes alternativas. Podes sempre mudar para .NET (C#) que não padece dos mesmos problemas, apesar de eu achar que o problema em questão não é particularmente relevante, pelas razões que já foram mencionadas num post mais acima.
     
    Última edição: 13 de Dezembro de 2008

Partilhar esta Página