» Início » Programação » Java » Tipos genéricos em Java (Generics)
 
Avaliação: | Publicado em: 07/01/2008
Tipos genéricos em Java (Generics)
Dayvid Lima Desenvolvedor Java há mais de 5 anos, atualmente consultor java em empresa multinacional utilizando recursos avançados da tecnologia J2EE com servidores de aplicação em plataforma Solaris para gerenciamento de redes e integração de sistemas.


Muitas pessoas tem me perguntado sobre "Generics", quem trabalha com linguagens de programação como C++ já deve estar acostumado, porém, tipos genéricos vem sendo uma novidade para muitos.
Espero com esse artigo esclarecer algumas dúvidas e dar uma pequena visão do que é e como pode ser utilizado.

A adoção do uso de tipos genéricos em Java levou muito tempo acredito que pelo fato da possibilidade de realização de "casting", porém quem nunca se deparou com uma "ClassCastException" quando acidentalmente tentou realizar um "casting" para o tipo errado.
Com tipos genéricos através de parametrização a verificação do "casting" é realizada no momento da compilação, o que torna mais fácil a vida do programador.

Antes de mostrar o exemplo de tipos genéricos, vamos analisar o seguinte cenário:

Iremos criar duas classes, a primeira "Obj" contém dois métodos (add e get) que recebem e retornam um tipo "Integer".

public class Obj {
 
    private Integer i;
    
    public void add(Integer i){
        this.i = i;
    }
    public Integer get(){
        return this.i;
    }
 }

A segunda classe utiliza a classe Obj para "guardar" um objeto:

public class UsaObj {

   public static void main(String[] args) {

        // apenas objetos do tipo Integer podem ser
        // armazenados em Obj
        Obj integerObj = new Obj();
        integerObj.add(new Integer(10));
        
        Integer someInteger = (Integer)integerObj.get();
        System.out.println(someInteger);
        
        // se algum programador por exemplo tentar
        // colocar uma String dentro de Obj
        // não será possível uma vez que add recebe
        // apenas um Integer.
        // (para ver o erro descomente as linhas abaixo)
        /*
        Obj stringObj = new Obj();
        stringObj.add("Teste");

        String someString = (String)stringObj.get();
        System.out.println(someString);
        */
    }
}

No caso acima, somente é possível colocar em Obj um objeto do tipo Integer, agora veremos como tipos genéricos pode nos ajudar quando queremos colocar um Integer ou uma String na classe Obj por exemplo.
Vamos recriar o cenário anterior com a utilização de tipos genéricos.

Veja que agora o tipo de objeto que será armazenado é representado pela letra T, que também deverá ser informado quando uma instância de Obj for criada.

public class ObjGen<T>{
 
    private T t; // T é o tipo do objeto
    
    public void add(T t){
        this.t = t;
    }
    public T get(){
        return this.t;
    }
 }

Agora vamos criar uma classe que utiliza a classe ObjGen.

public class UsaObjGen {

   public static void main(String[] args) {

        // veja que agora eu defino que tipo de objetos
        // podem ir dentro de ObjGen
        // nesse caso Integer
        ObjGen<Integer> integerObj = new ObjGen<Integer>();
        integerObj.add(new Integer(10));
        
        Integer someInteger = (Integer)integerObj.get();
        System.out.println(someInteger);

        // agora utilizaremos o mesmo objeto ObjGen para
        // guardar um tipo String
        ObjGen<String>  stringObj = new ObjGen<String>();
        stringObj.add("Teste");

        String someString = (String)stringObj.get();
        System.out.println(someString);
    }
}

Generics com "tipo mínimo"

Podemos utilizar um "tipo mínimo" para garantir um tipo obrigatório quando criamos classes genéricas.

public class ObjMin <T extends Runnable> {

    void inicia(T t){
        new Thread(t).start();
    }
}
Aqui estamos definindo que o tipo do objeto (T) deve ser no mínino um "Runnable".

Criaremos agora uma classe chamada Programa que implementa Runnable e utiliza o ObjMin.

public class Programa implements Runnable {
 
    public static void main(String[] args){

        // veja que defino o objeto ObjMin com o
        // tipo Programa (esta mesma classe)
        // como o objeto Programa estende Runnable eu
        // posso fazer isso
        ObjMin<Programa> o = new ObjMin<Programa>();
        o.inicia(new Programa());    
    }

    // será executado quando a classe for tratada
    // como uma thread e o método start foi chamado
    public void run(){
        System.out.println("ola");
    }
}

Existe ainda algumas aplicações para Generics que não abordei nesse artigo para não torna-lo muito extenso e chato de ler, a idéia aqui é dar uma pequena amostra de como funciona.

A utilização de "tipos genéricos" vêm sendo adotada cada vez mais pelos programadores java, também é possível aplicar "tipos genéricos" em interfaces, mas uma de suas maiores aplicações (pelo que vi nos trabalhos que realizei) é na manipulação de lista de objetos.

Espero que este artigo venha a sanar as dúvidas de quem ainda não utilizou "tipos genéricos" e/ou não conhecia.

Todos os exemplos utilizados aqui estão para download, também inclui um link do site da Sun onde é possível buscar mais informações sobre os "tipos genéricos" (Generics).

Abraços a todos e até o próximo.
Dayvid

Arquivos anexos ao artigo

Parabens, muito bom.
Abraço.