Java Generics: Um guia completo sobre como utilizar

Neste artigo apresentaremos a codificação de alguns exemplos visando demonstrar a importância do uso de Generics para as nossas aplicações.

Fique por dentro
Neste artigo apresentaremos a codificação de alguns exemplos visando demonstrar a importância do uso de Generics para as nossas aplicações. Este tema é importante a todo desenvolvedor interessado em aprimorar o seu código, aumentando sua legibilidade e reusabilidade, isto é, facilitando sua compreensão e a possibilidade de utilizar o mesmo código em outras aplicações, respectivamente. Este artigo demonstra como criar um sistema simples para gerenciar um estacionamento sem utilizar o recurso de Generics do Java. Durante o mesmo, conheceremos alguns riscos de seguir com esta decisão.

Em um projeto de software utilizamos, em média, apenas 20% do tempo em desenvolvimento, e os outros 80%, em manutenção. A ocorrência de erros é um dos principais motivos para a alteração de código, e, em alguns casos, até a sua reescrita. Nesse contexto, é importante a adoção de boas práticas de programação para a escrita de códigos legíveis e de fácil alteração, pois a ocorrência de bugs diminui na medida em que as aplicamos.

Para ajudar o desenvolvedor na adoção destas práticas, foi introduzido Generics na versão 5 da plataforma Java. Um recurso adicionado para fazer a verificação, em tempo de compilação, de tipos manipulados por uma classe. Como exemplo, podemos citar as classes da Collections API voltadas ao uso de conjuntos (List, Set e Map). Um dos motivos para a inclusão de Generics é a garantia de que pelo menos um tipo de objeto será relacionado a estas classes, deixando claro para o profissional com quais elementos ele está trabalhando em uma coleção. Por exemplo, podemos ter um objeto List gerenciando outros Double e outra coleção responsável por objetos Calendar. Ao programar desta maneira, evitamos o uso de uma única lista para ambos, tornando o código mais claro para o desenvolvedor.

Outro objetivo da inclusão de Generics é a redução de bugs em tempo de execução. Com ele, é possível a captura de erros na compilação, alertando o desenvolvedor sobre a ocorrência de exceções comuns, como uma ClassCastException. Consequentemente, fornece um meio para a escrita de um código mais seguro.

A reusabilidade também faz parte do recurso. Utilizando novamente uma classe da API de Collections como exemplo, podemos criar listas de String, outras de Integer e outras para qualquer classe. Desta forma, evitamos a escrita de código repetido e desnecessário.

Nesse cenário, o objetivo deste artigo é a apresentação de Generics ao desenvolvedor, listando todos os benefícios de sua utilização. Por meio de exemplos, os problemas que podem ser causados pelo não uso deste são apontados ao leitor. E no segundo artigo da minissérie, os mesmos exemplos serão apresentados, mas aplicando o novo conceito e explicitando porque este é a solução para as falhas decorrentes.

Desenvolvimento antes de Generics

Para demonstrar como é realizada a codificação sem o uso de Generics, vamos imaginar o seguinte cenário: precisamos criar uma lista para o armazenamento de objetos de um determinado tipo. Para esta finalidade, vamos trabalhar com o exemplo a seguir: em um estacionamento, há vagas para vários tipos de veículo, como Carros, Motocicletas e Ônibus. A representação destes modelos está no diagrama de classes da Figura 1.

Figura 1. Diagrama de classes da UML representando o Estacionamento e seus respectivos tipos de veículo

As implementações destas classes, que originarão os objetos a serem armazenados no estabelecimento, encontram-se nas Listagens 1, 2, 3 e 4.

Listagem 1. Veiculo.java: representa um veículo
package br.com.devmedia.javamagazine.generics.estacionamento.veiculos; public abstract class Veiculo { protected String nome; protected String marca; protected String cor; public Veiculo(String nome, String marca, String cor) { this.nome = nome; this.marca = marca; this.cor = cor; } public abstract String listarDados(); // métodos representando funcionalidades de um veículo // como ligar, desligar, acelera e frear // setters e getters omitidos }
Listagem 2. Carro.java: representa um carro
package br.com.devmedia.javamagazine.generics.estacionamento.veiculos; public class Carro extends Veiculo { public Carro(String nome, String marca, String cor) { super(nome, marca, cor); } @Override public void listarDados() { return "Nome do carro: " + nome + "\nMarca: " + marca + "\nCor: " + cor; } // métodos representando funcionalidades de um veículo // como ligar, desligar, acelerar e frear // setters e getters omitidos }
Listagem 3. Motocicleta.java: representa uma motocicleta
package br.com.devmedia.javamagazine.generics.estacionamento.veiculos; public class Motocicleta extends Veiculo { public Motocicleta(String nome, String marca, String cor) { super(nome, marca, cor); } @Override public String listarDados() { return "Nome da motocicleta: " + nome + "\nMarca: " + marca + "\nCor: " + cor; } // métodos representando funcionalidades de um veículo // como ligar, desligar, acelerar e frear // setters e getters omitidos }
Listagem 4. Onibus.java: representa um ônibus
package br.com.devmedia.javamagazine.generics.estacionamento.veiculos; public class Onibus extends Veiculo { public Onibus(String nome, String marca, String cor) { super(nome, marca, cor); } @Override public String listarDados() { return "Nome do onibus: " + nome + "\nMarca: " + marca + "\nCor: " + cor; } // métodos representando funcionalidades de um veículo // como ligar, desligar, acelerar e frear // setters e getters omitidos }

A Listagem 1 apresenta o código de uma classe abstrata para um veículo com os seus métodos e atributos representando aspectos do mundo real, como "

[...] continue lendo...

Artigos relacionados