Todo o processo é feito automaticamente em tempo de execução Java. Mas cuidados devem ser tomados durante a implementação desse recurso caso contrário, terá efeito negativo sobre o desempenho do aplicativo.
Antes do JDK 1.5, não era fácil para converter tipos de dados primitivos, por exemplo int, char, float, double em seu objeto equivalente (classes Wrapper) - Integer, Character, Float, Double. O JDK 5 veio com o recurso de conversão automática de tipos de dados primitivos em seu objeto equivalente. Esse recurso é conhecido como autoboxing. O contrário disto é conhecido como unboxing, ou seja, o processo de conversão de objetos em tipos primitivos de dados correspondentes é chamado de unboxing. Exemplo de código para ambos autoboxing e unboxing é mostrado como abaixo:
autoboxing
Integer integer = 9;
unboxing
int in = 0;
in = new Integer(9);
Quando Autoboxing e Unboxing são usados?
Autoboxing é aplicada pelo compilador do Java nas seguintes condições:
- Quando um valor primitivo é passado como um parâmetro para um método que espera um objeto da classe Wrapper correspondente.
- Quando um valor primitivo é atribuído a uma variável da classe Wrapper correspondente.
Considere o seguinte exemplo:
Listagem 1: Exemplo de código utilizando Autoboxing
public int sumEvenNumbers(List<Integer> intList ) {
int sum = 0;
for (Integer i: intList )
if ( i % 2 == 0 )
sum += i;
return sum;
}
Antes do JDK 1.5, o trecho de código acima resultaria em erro de compilação desde o operador resto - '%' e a expressão - '+ =' não poderia ser aplicada em números inteiros. Mas desde o JDK 1.5 este pedaço de código compila e roda sem nenhum erro, pois converte um Integer para int em tempo de execução.
Unboxing é aplicada pelo compilador do Java nas seguintes condições:
- Quando um objeto é passado como um parâmetro para um método que espera um valor primitivo correspondente.
- Quando um objeto é atribuído a uma variável do tipo primitivo correspondente.
Considere o seguinte exemplo:
Listagem 2: Exemplo de código mostrando Unboxing
import java.util.ArrayList;
import java.util.List;
public class UnboxingCheck {
public static void main(String[] args) {
Integer in = new Integer(-8);
// 1. Unboxing through method invocation
int absVal = absoluteValue( in );
System.out.println( "absolute value of " + in + " = " + absVal );
List<Double> doubleList = new ArrayList<Double>();
// It is autoboxed through method invocation.
doubleList.add(3.1416);
// 2. Unboxing through assignment
double phi = doubleList.get(0);
System.out.println( "phi = " + phi );
}
public static int absoluteValue( int i ) {
return (i < 0) ? -i : i;
}
}
Autoboxing e Unboxing permitem que o desenvolvedor escreva seu código forma fácil de ler e entender. A tabela a seguir mostra os tipos de dados primitivos e seus objetos delimitadores correspondentes:
Tipo Primitivo | Classe Wrapper |
boolean | Boolean |
byte | Byte |
char | Character |
float | Float |
int | Integer |
long | Long |
short | Short |
Tabela 1: tipo de dados primitivos e suas classes Wrapper equivalentes
Com operadores de comparação: Autoboxing e Unboxing podem ser feitos com os operadores de comparação. O seguinte trecho de código ilustra como isso pode ser feito:
Listagem 3: Exemplo de código mostrando Autoboxing e unboxing usando operadores de comparação
public class BoxedComparator {
public static void main(String[] args) {
Integer in = new Integer(25);
if (in < 35)
System.out.println("Value of int = " + in);
}
}
Autoboxing e Unboxing com sobrecarga de método: Autoboxing ou Unboxing podem ser feitos em caso de sobrecarga de método. Isto acontece com base nas seguintes regras:
Ampliação bate boxe - Quando há uma situação de escolher entre alargamento e boxe, ampliação leva a preferência:
Listagem 4: Exemplo de código mostrando preferência de sobrecarga
public class WideBoxed {
public class WideBoxed {
static void methodWide(int i) {
System.out.println("int");
}
static void methodWide( Integer i ) {
System.out.println("Integer");
}
public static void main(String[] args) {
short shVal = 25;
methodWide(shVal);
}
}
}
A saída deste programa é – int
Ampliação bate VarArgs - Quando há uma situação de escolher entre ampliação e varargs, ampliação tem a preferência
Listagem 5: Exemplo de código mostrando preferência sobrecarga
public class WideVarArgs {
static void methodWideVar(int i1, int i2) {
System.out.println("int int");
}
static void methodWideVar(Integer... i) {
System.out.println("Integers");
}
public static void main( String[] args) {
short shVal1 = 25;
short shVal2 = 35;
methodWideVar( shVal1, shVal2);
}
}
Boxe bate VarArgs - Quando houver uma situação que escolher entre boxe e varargs, boxe leva a preferência
Listagem 6: Exemplo de código mostrando preferência sobrecarga
public class BoxVarargs {
static void methodBoxVar(Integer in) {
System.out.println("Integer");
}
static void methodBoxVar(Integer... i) {
System.out.println("Integers");
}
public static void main(String[] args) {
int intVal1 = 25;
methodBoxVar(intVal1);
}
}
Guardar na mente para usar Autoboxing
Como sabemos que todo bom recurso vem com alguns inconvenientes, Autoboxing não é uma exceção a este respeito. Algumas dicas importantes que o desenvolvedor deve manter em mente ao usar esse recurso são como abaixo:
Comparando objetos com operador de igualdade - o operador de igualdade - "==" conduz à confusão, pois ele pode ser aplicado a ambos os tipos de dados primitivos e objetos. Quando o operador é aplicada nos objectos, ele realmente compara a referência de um dos objectos, e não os valores.
Listagem 7: Exemplo de código mostrando comparação
public class Comparator {
public static void main(String[] args) {
Integer istInt = new Integer(1);
Integer secondInt = new Integer(1);
if (istInt == secondInt) {
System.out.println("both one are equal");
} else {
System.out.println("Both one are not equal");
}
}
}
Misturando objeto e primitivo na igualdade e operador relacional - Se compararmos um tipo de dados primitivo com um objeto, o unboxing ocorre que pode lançar um NullPointerException se o objeto for nulo.
Cached Object - Desde o método valueOf () é usada para criar objetos primitivos encaixotados, os objetos usados são armazenados em cache. Desde java armazena números inteiros a partir de: 128-128, estes objetos em cache podem se comportar de forma diferente.
Degradação do desempenho do - Autoboxing ou unboxing diminui a performance de um aplicativo, pois cria um objeto indesejado que leva o GC para executar mais freqüência.
Desvantagem de Autoboxing
Embora autoboxing tenha várias vantagens, ele possui a seguinte desvantagem:
Caso o Autoboxing aconteça dentro de um loop de objetos desnecessários, pode diminuir o desempenho da aplicação. Considere o seguinte código:
Listing 8: Exemplo de código mostrando problema de desempenho
public int sumEvenNumbers(List<Integer> intList) {
int sum = 0;
for (Integer i: intList)
if ( i % 2 == 0 )
sum += i;
return sum;
}
Neste pedaço de código, soma + = i; irá expandir como soma = soma + i;. Desde o '+' operação não pode ser feita em objeto Integer, a JVM dispara o unboxing da soma Integer Objeto e, em seguida, o resultado é executa autoboxing volta.
Antes do JDK 1.5, os tipos de dados int e Integer eram distintos e em caso de sobrecarga de método estes dois tipos foram usados sem qualquer aborrecimento. Agora, com autoboxing e unboxing, este tornou-se mais complicado. Um exemplo disto é o método sobrecarregado em remover ArrayList. Classe ArrayList tem dois métodos de remover - remover (index) e remover (objeto). Neste caso, a sobrecarga de métodos não acontecerá e respectivo método será chamado com parâmetros apropriados.
Conclusão
Autoboxing é o mecanismo para converter um tipo de dados primitivo na respectiva embalagem ou objeto. O compilador usa valueOf () método para converter primitivo para Object e usa intValue (), doubleValue (), etc., para obter o valor primitivo do objeto. Em autoboxing, um boolean é convertido para booleano, byte a byte, char de caráter, as mudanças flutuador para Float, int vai para Integer, long vai convertidos curto eo longo para curto, enquanto que no unboxing a conversão acontece no sentido inverso.
Artigo traduzido e originalmente publicado em: http://mrbool.com/autoboxing-and-unboxing-in-java/28238