Neste artigo, veremos um recurso em Java chamado
autoboxing/unboxing . Autoboxing e unboxing são funções de conversão de tipos primitivos em tipos de objetos e vice-versa.
Todo o processo é executado automaticamente pelo Java Runtime Environment (JRE). Mas você deve ter cuidado ao implementar esta função, porque... Isso pode afetar o desempenho do seu programa.
Introdução
Nas versões anteriores ao JDK 1.5, não era fácil converter tipos de dados primitivos como
int
,
char
,
float
,
double
em suas classes wrapper Integer, Character, Float, Double. A partir do JDK 5, esta funcionalidade, convertendo tipos primitivos em objetos equivalentes, é implementada automaticamente. Esta propriedade é conhecida como
Autoboxing . O processo inverso, respectivamente, é
Unboxing , ou seja. o processo de conversão de objetos em seus tipos primitivos correspondentes. O código de exemplo para autoboxing e unboxing é fornecido abaixo:
Autoboxing
Integer integer = 9;
Desembalagem
int in = 0;
in = new Integer(9);
Quando é usada a embalagem e desembalagem automática? Autoboxing é usado pelo compilador Java nas seguintes condições:
- Quando um valor de um tipo primitivo é passado para um método como parâmetro de método, que espera um objeto da classe wrapper correspondente.
- Quando um valor de um tipo primitivo é atribuído a uma variável da classe wrapper correspondente.
Considere o seguinte exemplo:
Listagem 1: Código simples mostrando 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 código acima teria causado um erro de compilação porque o operador restante % e o unário mais += não podiam ser aplicados a uma classe wrapper. Mas no jdk 1.5 e superior esse código compila sem erros, convertendo Integer em
int
. O unboxing é usado pelo compilador Java nas seguintes condições:
- Quando um objeto é passado como parâmetro para um método que espera um tipo primitivo correspondente.
- Quando um objeto é atribuído a uma variável do tipo primitivo correspondente.
Considere o seguinte exemplo:
Listagem 2: Código simples mostrando unboxing
import java.util.ArrayList;
import java.util.List;
public class UnboxingCheck {
public static void main(String[] args) {
Integer in = new Integer(-8);
int absVal = absoluteValue(in);
System.out.println("absolute value of " + in + " = " + absVal);
List<Double> doubleList = new ArrayList<Double>();
doubleList.add(3.1416);
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 código fácil de ler e entender. A tabela a seguir mostra os tipos de dados primitivos e seus objetos wrapper correspondentes.
Tipos primitivos |
Aulas de concha |
boleano |
boleano |
byte |
Byte |
Caracteres |
Personagem |
flutuador |
Flutuador |
interno |
Inteiro |
longo |
Longo |
curto |
Curto |
Tabela 1: Tipos primitivos e classes wrapper equivalentes com operadores de comparação Autoboxing e unboxing podem ser usados com operadores de comparação. O trecho de código a seguir ilustra como isso acontece:
Listagem 3: Código de exemplo mostrando autoboxing e unboxing com um operador 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);
}
}
Autoempacotamento e descompactação ao sobrecarregar um método A compactação e descompactação automática são executadas ao sobrecarregar um método com base nas seguintes regras:
- A expansão “derrota” a embalagem numa situação em que há uma escolha entre expansão e embalagem; a expansão é preferível.
Listagem 4: Exemplo de código mostrando o benefício da 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);
}
}
}
Saída do programa - tipo
int
- A expansão supera o número variável de argumentos Numa situação em que se torna uma escolha entre expansão e número variável de argumentos, a expansão é preferível.
Listagem 5: Exemplo de código mostrando o benefício da 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);
}
}
- O empacotamento supera o número variável de argumentos Em uma situação em que se torna uma escolha entre o empacotamento e o número variável de argumentos, o empacotamento é preferível.
Listagem 6: Exemplo de código mostrando o benefício da 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);
}
}
Você deve manter o seguinte em mente ao usar o Auto Packing: Como sabemos, todo bom recurso tem uma desvantagem. A embalagem automotiva não é exceção nesse aspecto. Algumas notas importantes que um desenvolvedor deve ter em mente ao usar este recurso:
- Comparar objetos com o
==
operador '' pode ser confuso, pois pode ser aplicado a tipos e objetos primitivos. Quando este operador é aplicado a objetos, ele na verdade compara referências aos objetos, não aos próprios objetos.
Listagem 7: Exemplo de código mostrando a 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 objetos e tipos primitivos com operadores de igualdade e relacionais. Se compararmos um tipo primitivo com um objeto, então o objeto é unboxed, o que pode ser lançado
NullPointerException
se o object null
.
- Cache de objetos. O método
valueOf()
cria um contêiner de objetos primitivos que ele armazena em cache. Como os valores são armazenados em cache no intervalo de -128 a 127, inclusive, esses objetos armazenados em cache podem se comportar de maneira diferente.
- Degradação de desempenho. Autoboxing ou unboxing degrada o desempenho do aplicativo porque cria um objeto indesejado que força o coletor de lixo a ser executado com mais frequência.
Desvantagens do AutoBoxing Embora o AutoBoxing tenha diversas vantagens, ele apresenta as seguintes desvantagens:
Listagem 8: Código de amostra mostrando o problema de desempenho.
public int sumEvenNumbers(List intList) {
int sum = 0;
for (Integer i : intList) {
if (i % 2 == 0) {
sum += i;
}
}
return sum;
}
Nesta seção do código,
sum +=i
ele será expandido para
sum = sum + i
. Começando com o
+
operador ' ', a JVM inicia o unboxing porque o
+
operador ' ' não pode ser aplicado a um objeto Integer. E então o resultado é compactado automaticamente. Antes do JDK 1.5, os tipos de dados
int
e inteiros eram diferentes. Em caso de sobrecarga do método, esses dois tipos foram utilizados sem problemas. Com o advento da embalagem/desembalagem automática, isto tornou-se mais difícil. Um exemplo disso é o método sobrecarregado
remove()
em
ArrayList
. A classe
ArrayList
possui dois métodos delete -
remove(index)
e
remove(object)
. Neste caso, a sobrecarga do método não ocorrerá e o método correspondente será chamado com os parâmetros apropriados.
Conclusão
Autoboxing é um mecanismo para converter implicitamente tipos de dados primitivos em classes wrapper (objetos) correspondentes. O compilador usa o método
valueOf()
para converter tipos primitivos em objetos, e os métodos
IntValue()
,
doubleValue()
etc., para obter os tipos primitivos do objeto. Autoboxing converte o tipo booleano
boolean
em Boolean,
byte
em Byte,
char
em Character,
float
em Float,
int
em Integer,
long
em Long,
short
em Short. A desembalagem ocorre na direção inversa.
Artigo original
GO TO FULL VERSION