Ir para o conteúdo

Wrappers de Tipos Primitivos

Java não é uma linguagem orientada a objectos pura, como vimos antes, existem tipos de dados em Java que não são objectos, os chamados tipos primitivos.

No entanto, as situações onde podemos querer usar os tipos primitivos como se objectos fossem são bastante comuns, imaginem quer pretendem usar estruturas de dados como uma hashtable, quem que a chave é um objecto que mapeia para outros objectos que guardamos. Nesta situação não conseguimos usar os tipos primitivos nem como chave, nem para ficarem guardados no hashtable.

Para contornar esta situação, foram criados as classes wrapper que permite envolver um tipo primitivo num objecto que o represente.

Tipo primitivo Classe wrapper
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double

Todos estas classes permite a conversão entre os tipos primitivos e objectos bem como a operação inversa. Possuem também métodos que permite converter para uma representação em String ou, caso tenhamos o valor em String, passar para o tipo primitivo.

Boxing/Unboxing

Ao processo de converter um tipo primitivo para o seu wrapper equivalente chamamos boxing, ao processo inverso unboxing. O Java oferece-nos uma forma de tornar este processo automático através da funcionalidade de autoboxing.

import java.util.*;

public class Frequency {
   public static void main(String[] args) {
      Map<String, Integer> m = new TreeMap<String, Integer>();
      for (String word : args) {
          Integer freq = m.get(word);
          //conversão automática para Integer, tanto na 
          //soma (Integer - Objecto + int - primitivo) como 
          //na passagem para um método que receber um objecto
          m.put(word, (freq == null ? 1 : freq + 1)); 
      }
      System.out.println(m);
   }
}

Exemplo mais complexo que mistura classes anónimas:

public static List<Integer> asList(final int[] a) {
    return new AbstractList<Integer>() {

        public Integer get(int i) { return a[i]; }

        public Integer set(int i, Integer val) {
            Integer oldVal = a[i];
            a[i] = val;
            return oldVal;
        }

        public int size() { return a.length; }
    };
}

O processo de autoboxing irá penalizar a performance da nossa aplicação, no exemplo que usa a lista, a implementação serão mais lenta que não usando autoboxing. Por esse motivo a utilização de autoboxing deve ser ponderada e evitada em situações onde a performance é um factor crítico.

Deverá ser usado quando existe uma necessidade de conversão entre tipos de dados diferentes1, nomeadamente entre tipos primitivos e objectos, por exemplo, se for necessário colocar tipos primitivos dentro de estruturas de dados com listas, hashtables, etc.

As classes wrapper não são substitutas dos tipos primitivos, um Integer não substitui um int, e não devem ser usados em processo exigentes computacionalmente, onde a performance é um factor crítico ou em computação científica. Embora o autoboxing aproxime os tipos primitivos dos seus wrappers correspondentes, a diferença entre os dois continua a existir.


  1. O termo correcto será impedance mismatch