As novidades do Java 1.5

Você sabe quais novidades foram introduzidas no Java 1.5? A melhor de todas foi a implementação de Generics, a nova tecnologia que vai facilitar e muito a vida dos programadores Java. Neste artigo faço uma introdução completa às novas implementações encontradas nessa versão dessa linguagem.

[ Hits: 53.853 ]

Por: Perfil removido em 11/10/2005


Generics



Uma classe genérica é uma classe com um ou mais tipos de variáveis. Nesta seção, estou usando uma classe Objekt simples como um exemplo. Esta classe nos permite focalizarmos apenas no estudo de generics sem distração com os detalhes de armazenamento de dados. Segue abaixo o código da classe Objekt genérica:

public class Objekt<T>
{
   private T var;

   public Objekt()
   {
      this.var = null;
   }

   public Objekt(T var)
   {
      this.var = var;
   }
  
   public void setVariavel(T newvar)
   {
      this.var = newvar;
   }

   public T getVariavel()
   {
      return (var);
   }
}

A classe Objekt apresenta um tipo de variável T, inclusa dentro de parênteses de ângulo < >, depois do nome da classe. Uma classe genérica pode ter mais de um tipo de variável. Por exemplo, eu poderia definir a classe Objekt com tipos separados para o primeiro e segundo campos:

public class Objekt<T,K>
{
   . . .
}

As variáveis de tipos são usadas dentro da classe para especificar os tipos retornados pelos métodos, os tipos de parâmetros de entrada e variáveis locais da classe. Por exemplo:

private T var;

Você instancia os tipos genéricos substituindo os tipos para as variáveis de tipo, como:

Objekt<String> objeto = new Objekt<String>("Viva o Linux");

O resultado disto seria uma classe assim:

public class Objekt
{
   private String var;

   public Objekt()
   {
      this.var = null;
   }

   public Objekt(String var)
   {
      this.var = var;
   }
  
   public void setVariavel(String newvar)
   {
      this.var = newvar;
   }

   public String getVariavel()
   {
      return (var);
   }
}

Também pode-se instanciar uma classe genérica como uma classe ordinária. Nesse caso o parâmetro passado a classe é a superclasse Object.

Objekt objeto = new Objekt();

Em resumo, uma classe genérica nada mais é do que uma fábrica de classe ordinárias (comuns).

public class Test
{
  public static void main(String args[])
  {
     Objetkt<String> program = new Objekt("Viva o Linux");
     System.out.println(program.getVariavel());
  }
}

Uma das mudanças no novo JDK 1.5 apresenta é que a classe java.lang.Class é genérica. Este é um interessante exemplo da capacidade de uso dos genéricos para qualquer tipo de container.

Como nem tudo são flores, as novas modificações de Java melhoram e muito a linguagem, mas existem algumas restrições e limitações nessas melhorias.

Infelizmente um a programação genérica tem uma observação, ela não pode ser utilizada para tipos primitivos. Isso quer dizer que só pode utilizar dela par tipos objetos e seus derivados. Por exemplo, a classe abaixo vai acusar um erro de compilação:

public class Teste<double>
{
  ...
}

Você não poderá declarar um array como uma variável de tipo, o código abaixo está completamente errado:

Objekt<Integer> array[] = new Objekt<Integer>(10);

Mas se você quer um conjunto de de variáveis de tipos, recomendo usar a classeArrayList. O código abaixo está correto:

ArrayList<Objekt<Integer>> array = new ArrayList<Objekt<integer>>();

Você não poderá inicializar tipos genéricos. Por exemplo, o construtor abaixa está completamente ilegal:

public Objekt()
{
  var = new T();
}

Similarmente, você não poderá criar um array de genéricos:

public <T> T[] getMax(T[] vetor)
{
  T[] temp = new T[10];
  ...
}

Você não pode referenciar variáveis de tipo como campos estáticos. Por exemplo, o código abaixo vai acusar um erro de compilação:

public class Primos<T>
{
  private static T temp;

  public static T createArray()
  {
    if(temp == null)
    return temp;
  }
}

O conceito de genéricos foi extendido não só a classes mas também para métodos.

public <T> T getMiddle(T[] vetor)
{
  return vetor[vetor.length / 2];
}

Note que este método é definido dentro de uma classe ordinária e não dentro de uma classe genérica. Porém este é um método genérico, como você pode ver. Note que os tipos de variáveis são inseridas depois dos modificadores e antes dos tipos de retorno.

Você pode definir métodos genéricos para ambos os casos, dentro de uma classe ordinário ou dentro de uma classe genérica.

Quando você quiser chamar um método genérico você deve definir o tipo dentro dos parênteses de ângulo e antes do nome do método:

String path = {"Viva","o ,"Linux"};
String middle = Test.<String>getMiddle(path);

Neste caso (e em muitos outros), você pode omitir os tipos de parâmetros de entrada da chamada do método. O compilador já tem informação o bastante para deduzir que tipo de método você quer. Isto é, ele sabe que o tipo da variável path (neste caso, uma array de String)m compara com o tipo genérico T[] e deduz que é do tipo String. Você ainda pode simplificar ainda mais a chamada, como:

String middle = Test.getMiddle(path);

Mas algumas vezes os métodos precisam de uma restrição ao parâmetro que vai receber. No exemplo abaixo, o método compara dois parâmetros de entrada para verificar qual deles é o maior.

public static <T> T max(T x, T y, T z)
{
   T result = x;
   if(result.compareTo(y) > 0)
     result = y;
   if(result.compareTo(z) > 0)
     result = z;
   return (result);
}

Bem, o problema óbvio que existe é que nem todas as classes implementam a interface Comparable, logo o método compareTo() não existe nessas classes. Para que não ocasione em um erro de execução, deve-se impor limite para que o tipo de variável passada implemente a interface Comparable. Para isso utilizamos da palavra chave "extends", que nesse contexto indica que o objeto será um subtipo de Comparable.

public static <T extends Comparable> T max(T x, T y, T z)
{
   T result = x;
   if(result.compareTo(y) > 0)
     result = y;
   if(result.compareTo(z) > 0)
     result = z;
   return (result);
}

Aqui a palavra-chave "extends" é sobrecarregada, em lugar de ser criada uma nova palavra-chave. Neste código se mostra que o tipo T tem como "limite inferior" a classe Comparable.

Você pode ter mais de um limite para o tipo de parâmetro a ser passado. Os limites de tipo devem ser separados pelo operador "&".

public static <T extends Comparable & Serializable> T max(T x, T y, T z)
Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Loops, Autoboxing/Unboxing, Collections, Static Import, Scanner, Support for Enviromment Variables, Threads
   3. LookAndFeels, Math, Swing, Printf, ProcessBuilder, Callables, Bit Manipulation Operations
   4. StringBuilder, Varargs, Enums, Generic ArrayList, Formatter, Concurrency, AWT, Monitoring and Management
   5. Generics
   6. Conclusão
Outros artigos deste autor

IPtables - Trabalhando com Módulos

Formatando texto no Open Office

Xen - XL.cfg - Sintaxe da Configuração de Domínios - Parte II

Instalando o Ubuntu no pendrive

LookXP-IceWM - Linux leve e com cara de XP

Leitura recomendada

Lançamento do GFP 0.1.4.5 - Gerenciador Financeiro Pessoal

Terasology: O Minecraft gratuito e com gráfico realista

Declaração de IRPF 2006 pelo Linux

JlGui - Java Media Player

Introdução ao framework Mentawai

  
Comentários
[1] Comentário enviado por [email protected] em 11/10/2005 - 15:39h

Parabéns pelo fantástico artigo... Achei as tuas explicações bastante acessíveis. Estou ansioso por experimentar algumas destas novidades na linguagem.

[2] Comentário enviado por lennon.jesus em 11/10/2005 - 16:37h

A linguagem JAVA está surpreendendo cada vez mais. O C e o C++ estão sendo substituidos em muitas universidades pelo JAVA.

Eu também aprecio as linguagens DotNet da Microsoft mas a grande vantagem do JAVA está em sua portabilidade entre plataformas e suas ferramentas de desenvolvimentos gratuitas.

Briga acirrada mesmo teríamos se a Microsoft disponibilizasse a portabilidade em sua DotNet. Seria interessante... Até mesmo se as ferramentas (deles) continuassem sendo pagas.

Acho que nos próximos anos iremos experimentar evoluções em diversas áreas, tanto de software como de hardware.


Parabéns pelo ótimo (inteligente, claro e direto) artigo.


Abraços.

[3] Comentário enviado por rdaraujo em 13/10/2005 - 16:21h

Pessoal, tenho a versao 1.5.0, porem em alguns exemplos das novas funcionalidades, como a nova forma de varrer um array, aparece a seguinte mensagem:
Syntax error, 'for each' statements are only available if source level is 5.0.

Eis o codigo:

String[] ar = {"a","b","c","d"};
for (String i:ar) {
System.out.println(i);
}

$ javac -version
javac 1.5.0_01

[4] Comentário enviado por FelipeAbella em 01/06/2006 - 18:52h

rdaraujo: Você tem que configurar para usar o source level 5.0 no compilador, muitas IDEs podem configurar isso, ou voce pode procurar saber o parametro que faz isso, que eu nao lembro agora.

[5] Comentário enviado por kalib em 19/02/2008 - 18:35h

Comigo tá dando problema...
instalei o 1.5...e rodando o comando java -version
vejo que está na 1.5 mesmo..
Porém quando abro o eclipse por exemplo, dá erro... ele continua compilando com o 1.4, e a classe scanner acaba não funcionando... :/
Alguém tem alguma solução?

[6] Comentário enviado por M4conheiRoX em 23/10/2008 - 12:02h

vou comerça
ftz


Contribuir com comentário