Generics, inferência de tipos e reificação no Java 7

Muito tem se falado sobre o Java 7 SE e que mudanças na linguagem essa versão poderá trazer. Alex Miller criou um excelente post com muito links para JSRs e blogs sobre as propostas para a linguagem. Peter Ahe publicou também um interessante wish list.

Maneiras alternativas de criarmos coleções usando uma sintaxe mais enxuta já foram discutidas por Stephen Colebourne, Peter Ahe e Rafael Ferreira. Gostaria de salientar que o Java 5 já trouxe alguns métodos interessantes na Collections com essa finalidade. Exemplos são quando queremos criar uma coleção vazia ou com apenas um elemento:

List<String> x = Collections.emptyList();
List<Integer> y = Collections.singletonList(5);

Existem métodos análogos para a criação de conjuntos e mapas. A assinatura do método emptyList é <T> List<T> emptyList(). É interessante que a linguagem infere <T>, descobrindo que nesse primeiro caso T deve ser String. Mas isso nem sempre acontece:

 static void  metodo(List<String> lista) {
    // faz alguma coisa
  }
  
  // dentro do main:
  metodo(Collections.emptyList());

A invocação acima não compila, pois tenta fazer T como Object! Algumas pessoas acham que isso é um bug, mas o pessoal da Sun decidiu por não tentar inferir o tipo em determinadas situações. Na verdade, o compilador só tenta inferir o tipo em dois específicos casos: na clausula de return ou em uma atribuição.

A especificação da linguagem Java tem uma sintaxe especial no caso de você querer indicar qual é o tipo que deve ser utilizado em uma invocação de método genérico:

metodo(Collections.<String>emptyList());

Pronto! Agora o Java sabe que T deve ser String nessa invocação, e nosso código passa a compilar. Uma sintaxe esdruxula e pouco comum.

Enquanto todo mundo comenta sobre as closures do Java 7, sem dúvida meu principal interesse sobre o Java 7 é a reificação de tipos genéricos, isso é, em tempo de execução, poder determinar os tipos parametrizados de um objeto. Hoje em dia isso não é possível por causa da erasure, que mantém a compatibilidade com o código pré-generics: um objeto não sabe, em tempo de execução, quais são os tipos que foram usados nos seus parâmetros durante sua instanciação. Isso cria algumas clássicas questões nos fóruns, como “porque não posso criar uma array de T?” ou “Porque não posso usar T.class?“. Muitas pessoas consideram até a hipótese de quebrar a compatibilidade binária do Java, e fazem propostas interessantes para resolver esse problema.

Creio que o Java 7 trará muitas novas surpresas, algumas interessantes como as closures, outras infames como o suporte a literais XML dentro da linguagem. Só espero que eles continuem com a premissa do Java, de deixá-la legível e simples, e não façam como no C++, onde todo novo recurso interessante foi adicionado, tornando a linguagem de difícil legibilidade em alguns casos.

Tags:

3 Comentários

  1. Paulo Silveira 16/04/2007 at 00:41 #

    Para ficar registrado, outro ponto que gostaria muito de ver implementado no Java sao os literais para metodos, construtores e campos:

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5043025

  2. Renato 21/04/2007 at 15:41 #

    Legível e simples? Você ainda acha? 😀

    Dá uma olhada na JSR 308…

Deixe uma resposta