Por que eu devo ler este artigo: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.

Diagrama de classes da UML representando o Estacionamento e seus respectivos tipos de veículo
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 acelerar(), frear() e cor, respectivamente. Já as Listagens 2, 3 e 4 são referentes aos tipos específicos de automóveis que podem ser armazenados no estacionamento. Para a demonstração do artigo, apenas três tipos de veículo foram criados: Carro, Motocicleta e Onibus. Para facilitar a compreensão de Generics, métodos comuns a um veículo, como ligar() e acelerar(), não estão presentes nas listagens.

Para a representação do estacionamento e respectivo controle e gerenciamento dos veículos cadastrados, codificamos a Listagem 5. Métodos para adicionar novos veículos no local (adicionar()) e para a listagem dos mesmos (listarVeiculos()) estão nesta classe para mostrar suas principais funcionalidades e características. O atributo veiculos, declarado como um objeto do tipo List, refere-se aos veículos a serem armazenados no local.

...

Quer ler esse conteúdo completo? Tenha acesso completo