Vous êtes sur la page 1sur 4

1

1
Java Generics
Os tipos de dados genéricos fazem sua estréia em
Java
POR HERVAL FREIRE DE A. JÚNIOR (HERVAL@CNNT.COM.BR)

A Sun anunciou, no mês de Dezembro do ano passado, a disponibilização de um kit projetado


para demonstrar uma das inovações mais radicais dentre todas as novidades propostas para a
distribuição 1.5 do Java – a inclusão dos tipos genéricos.
Tipos genéricos, ou parametrizados, não são uma novidade para quem trabalha com outras
linguagens de programação, como por exemplo o C++. Apesar disso, a adoção deste mecanismo na
linguagem Java foi um processo longo e sujeito a sucessivos atrasos. Apesar da opinião de muitos
de que a utilização de tipos parametrizados é um recurso desnecessário graças à facilidade de se
trabalhar com typecasting na linguagem Java, a especificação da extensão de tipos genéricos (JSR-
14) apresenta ótimos argumentos para sua adoção, e mostra como este novo recurso pode facilitar a
vida do programador.

Benefícios
É provável que todo programador já tenha se deparado com exceções de conversão
(ClassCastExceptions) ao percorrer uma coleções de objetos que (geralmente por acidente) contém
objetos de um tipo não esperado. Este problema ocorre graças à forma como a linguagem Java
utiliza-se do typecasting para criar estruturas de dados genéricas.
A listagem 1 mostra um exemplo de código utilizando-se da sintaxe atual da linguagem Java.
Graças à ausência de verificação de tipos forte, o código compila corretamente, mas um erro em
tempo de execução impede que o programa funcione como esperado.

public static void main( String [] args )


{
List l = new ArrayList();

Integer i1 = new Integer( 1 );


Integer i2 = new Integer( 2 );
String i3 = "3"; // Irá causar um ClassCastException
Integer i4 = new Integer( 4 );

l.add( i1 );
l.add( i2 );
l.add( i3 );
l.add( i4 );

Iterator numbers = l.iterator();

while( numbers.hasNext() ) {
Integer integer = (Integer) numbers.next();
System.out.println( “” + integer.intValue() );

counter += integer.intValue();
}

Tipos parametrizados resolvem o problema facilmente: o que torna o mecanismo interessante é


que ele garante a integridade de uma estrutura de dados em tempo de compilação. Com a inclusão
de uma sintaxe de parametrização, a checagem estática de tipos detecta possíveis erros de casting e
1
Artigo publicado no site mundooo.com.br
2

abortar a compilação do programa, evitando que um trecho de código pouco visível venha a causar
uma grande dor de cabeça, no futuro.

Hello, Generics
A listagem 2 mostra um exemplo básico de utilização de tipos genéricos. Os comentários
mostram pontos onde o compilador acusa por erros, graças aos parâmetros indicando o tipo
esperado pela classe de coleção. Note que a sintaxe de parametrização é bastante simples: o tipo
utilizado de parâmetro é informado junto ao nome da classe (entre “<” e “>”), no momento de
instanciação dos objetos parametrizados. Este tipo é, a partir de então, utilizado em testes de
conversão (typecheckings) durante todo o processo de compilação, trazendo mais confiabilidade ao
código.

static public void main(String[] args) {


LinkedList<Integer> integerList = new LinkedList<Integer>();
integerList.add(new Integer(1));
integerList.add(new Integer(2));
/*
* Erro lançado
* cannot resolve symbol
* symbol : method add (java.lang.Integer)
*/
integerList.add(new String(“I will fail!”));

Iterator<Integer> listIterator = integerList.iterator();


String item;
while(listIterator.hasNext()) {
/* Erro lançado
* incompatible types
** found : java.lang.Integer
** required: java.lang.String
*/
item = listIterator.next(); // causes a compilation error
}
/* Erro de compilação
** incompatible types
** found : java.util.Iterator<java.lang.String>
** required: java.util.Iterator<java.lang.Integer>
*/
Iterator<String> = integerList.iterator();

// Nenhum erro de casting será lançado


while (listIterator.hasNext()) {
item = (Integer)listIterator.next();
}
}

Vale citar que, apesar da existência de uma nova sintaxe, os bytecodes gerados por um programa
que utiliza-se de tipos genéricos são totalmente compatíveis com versões anteriores do Java: a nova
especificação define que o código compilado utilizando-se dos tipos parametrizados deve ser
convertido para código comum (sem marcadores de parametrização), ao final da compilação –
fazendo com que o mecanismo de verificação de tipos funcione sem afetar a compatibilidade de
código da linguagem como um todo.

Um segundo exemplo
As listagens a seguir demonstram um exemplo de implementação de uma interface genérica. A
interface MyInterface (listagem 3) define um método que trabalha com tipos genéricos – e é
implementada para realizar a comparação de elementos em uma lista (listagem 4). O exemplo,
3

retirado do artigo de divulgação da prévia dos tipos genéricos, é bastante simples e demonstra uma
interface que pode ser implementada para comparar dois objetos de mesmo tipo – seja qual for o
tipo – sem necessidade de verificações ou castings explícitos.

import java.util.List;
interface MyInterface<X> {
public boolean containsBoth(X a, X b);
}

import java.util.*;
public class MyList<X> extends LinkedList<X>
implements MyInterface<X> {
public boolean containsBoth(X a, X b) {
return (contains(a) && contains(b));
}
public static <A> void swap(List<A> list, int i, int j) {
A temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
/*
** main
*/
public static void main( String[] args) {
// create list and add elements
MyList<String> theList = new MyList<String>();
theList.add("one");
theList.add("two");
theList.add("three");
// print out the list's contents
System.out.println("");
System.out.println("The list's contents are:");
ListIterator<String> theIterator= theList.listIterator(0);
while (theIterator.hasNext()) {
System.out.println(theIterator.next());
}
System.out.println("");
// use the containsBoth method
if (theList.containsBoth("one", "two")) {
System.out.println("The list contains both \"one\" and \"two\"");
}
// use the swap method
swap(theList, 0, 2);
// print out the list's contents
System.out.println("");
System.out.println("The list's contents are:");
theIterator = theList.listIterator(0);
while (theIterator.hasNext()) {
System.out.println(theIterator.next());
}
System.out.println("");
} // main
} // MyList
4

A tabela abaixo mostra exemplos de utilização da nova sintaxe para a declaração de tipos, métodos,
interfaces e classes parametrizadas segundo a especificação da Sun.

Vector<String> stringVector = new Vector<String>


List<Integer> integerList = new List<Integer>

interface List<Element> implements{...}


class MyList<Element> {...}
class MyList<Element> implements List<Element> {...}
boolean containsBoth(Element a, Element b);
static <Element> boolean swap(List<Element> list, int i, int j);

Uma prévia do que está por vir


No site da Sun é possível fazer o download de uma versão early access do compilador preparado
para tipos genéricos. Para testar o pacote. Na página de download, existe um conjunto de instruções
detalhando o que deve ser feito para testar um código utilizando os tipos genéricos. Em resumo, os
seguintes passos devem ser realizados:

1. Faça download do pacote de demonstração (adding_generics-1_3-ea.zip) e do JDK 1.4.1.


2. Após a instalação, configure as seguintes variáveis de ambiente:
JSR14DISTR – deve conter o caminho para o diretório no qual o pacote de demonstração foi
descompactado
J2SE14 – deve conter o caminho completo de instalação do JDK 1.4.1
3. Execute o makefile localizado no diretório examples do pacote de demonstração, em ambiente
Unix. Em ambiente Windows, um script de compilação pode ser localizado no diretório
scripts da distribuição.
4. Escreva seu próprio código genérico!

Conclusão
Os tipos genéricos são, na pior das hipóteses, uma novidade bastante curiosa. Prova de que o
poder de transformação exercido pelo JCP (Java Community Process) da Sun tem lutado para
manter a linguagem Java sempre viva, com novos recursos a cada versão. A inclusão da diretiva
assert na versão 1.4 do JDK e a nova adição à sintaxe a ser consolidada no JDK 1.5 mostram que
ainda existe muito a ser explorado no longo processo de evolução (e maturação) da linguagem Java.
Que venham as novidades!

Referências
JSR-14 (Java Generics) -
PolyJ – Uma implementação não-oficial dos tipos genéricos -
Generics Early Access - http://developer.java.sun.com/developer/earlyAccess/adding_generics/

Vous aimerez peut-être aussi