In questo articolo esamineremo una funzionalità di Java chiamata
autoboxing/unboxing . L'autoboxing e l'unboxing sono una funzione di conversione dei tipi primitivi in tipi di oggetto e viceversa.
L'intero processo viene eseguito automaticamente da Java Runtime Environment (JRE). Ma dovresti fare attenzione quando implementi questa funzione, perché... Può influenzare le prestazioni del tuo programma.
introduzione
Nelle versioni precedenti a JDK 1.5, non era facile convertire tipi di dati primitivi come
int
,
char
,
float
,
double
nelle rispettive classi wrapper Integer, Character, Float, Double. A partire da JDK 5, questa funzionalità, convertendo i tipi primitivi in oggetti equivalenti, viene implementata automaticamente. Questa proprietà è nota come
Autoboxing . Il processo inverso, rispettivamente, è
l'Unboxing , ovvero il processo di conversione degli oggetti nei corrispondenti tipi primitivi. Di seguito è riportato il codice di esempio per l'autoboxing e l'unboxing:
Autoboxing
Integer integer = 9;
Spacchettamento
int in = 0;
in = new Integer(9);
Quando viene utilizzato l'imballaggio e il disimballaggio automatico? L'autoboxing viene utilizzato dal compilatore Java nelle seguenti condizioni:
- Quando un valore di tipo primitivo viene passato a un metodo come parametro del metodo, che prevede un oggetto della classe wrapper corrispondente.
- Quando un valore di tipo primitivo viene assegnato a una variabile della classe wrapper corrispondente.
Considera il seguente esempio:
Listato 1: Codice semplice che mostra l'autoboxing
public int sumEvenNumbers(List<Integer> intList ) {
int sum = 0;
for (Integer i: intList )
if ( i % 2 == 0 )
sum += i;
return sum;
}
Prima di jdk 1.5, il codice precedente avrebbe causato un errore di compilazione perché l'operatore di resto % e unario più += non potevano essere applicati a una classe wrapper. Ma in jdk 1.5 e versioni successive questo codice viene compilato senza errori, convertendo Integer in
int
. L'unboxing viene utilizzato dal compilatore Java nelle seguenti condizioni:
- Quando un oggetto viene passato come parametro a un metodo che prevede un tipo primitivo corrispondente.
- Quando un oggetto viene assegnato a una variabile del tipo primitivo corrispondente.
Considera il seguente esempio:
Listato 2: Codice semplice che mostra l'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;
}
}
L'autoboxing e l'unboxing consentono allo sviluppatore di scrivere codice facile da leggere e comprendere. La tabella seguente mostra i tipi di dati primitivi e i corrispondenti oggetti wrapper.
Tipi primitivi |
Classi di shell |
booleano |
Booleano |
byte |
Byte |
car |
Carattere |
galleggiante |
Galleggiante |
int |
Numero intero |
lungo |
Lungo |
corto |
Corto |
Tabella 1: tipi primitivi e classi wrapper equivalenti con operatori di confronto È possibile utilizzare autoboxing e unboxing con operatori di confronto. Il seguente frammento di codice illustra come ciò accade:
Listato 3: Codice di esempio che mostra l'autoboxing e l'unboxing con un operatore di confronto
public class BoxedComparator {
public static void main(String[] args) {
Integer in = new Integer(25);
if (in < 35)
System.out.println("Value of int = " + in);
}
}
Autopacking e decompressione durante l'overload di un metodo L'autopacking e l'unpacking vengono eseguiti durante l'overload di un metodo in base alle seguenti regole:
- L’espansione “sconfigge” il packaging in una situazione in cui c’è una scelta tra espansione e packaging; l’espansione è preferibile.
Listato 4: Codice di esempio che mostra i vantaggi dell'overloading
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);
}
}
}
Output del programma: tipo
int
- L'espansione batte il numero variabile di argomenti In una situazione in cui diventa una scelta tra l'espansione e il numero variabile di argomenti, l'espansione è preferibile.
Listato 5: Codice di esempio che mostra i vantaggi dell'overloading
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);
}
}
- L'impacchettamento batte il numero variabile di argomenti In una situazione in cui diventa una scelta tra l'impacchettamento e il numero variabile di argomenti, l'impacchettamento è preferibile.
Listato 6: Codice di esempio che mostra i vantaggi dell'overload
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);
}
}
Dovresti tenere a mente le seguenti cose mentre usi Auto Packing: Come sappiamo, ogni caratteristica positiva ha uno svantaggio. L’imballaggio automobilistico non fa eccezione in questo senso. Alcune note importanti che uno sviluppatore dovrebbe tenere a mente quando utilizza questa funzionalità:
- Il confronto degli oggetti con l'
==
operatore '' può creare confusione, poiché può essere applicato a tipi e oggetti primitivi. Quando questo operatore viene applicato agli oggetti, confronta effettivamente i riferimenti agli oggetti, non gli oggetti stessi.
Listato 7: Codice di esempio che mostra il confronto.
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");
}
}
}
- Mescolare oggetti e tipi primitivi con gli operatori di uguaglianza e relazionali. Se confrontiamo un tipo primitivo con un oggetto, allora l'oggetto è unboxed, il che può lanciare un'eccezione
NullPointerException
se l'oggetto null
.
- Caching degli oggetti. Il metodo
valueOf()
crea un contenitore di oggetti primitivi che memorizza nella cache. Poiché i valori vengono memorizzati nella cache nell'intervallo da -128 a 127 inclusi, questi oggetti memorizzati nella cache potrebbero comportarsi diversamente.
- Degrado delle prestazioni. L'autoboxing o l'unboxing riducono le prestazioni dell'applicazione perché creano un oggetto indesiderato che forza l'esecuzione più frequente del Garbage Collector.
Svantaggi di AutoBoxing Sebbene AutoBoxing presenti numerosi vantaggi, presenta i seguenti svantaggi:
Listato 8: Codice di esempio che mostra il problema di prestazioni.
public int sumEvenNumbers(List intList) {
int sum = 0;
for (Integer i : intList) {
if (i % 2 == 0) {
sum += i;
}
}
return sum;
}
In questa sezione di codice
sum +=i
verrà espanso in
sum = sum + i
. A partire dall'operatore "
+
", la JVM avvia l'unboxing poiché l'
+
operatore "" non può essere applicato a un oggetto Integer. E poi il risultato viene compresso automaticamente. Prima di JDK 1.5, i tipi di dati
int
e Integer erano diversi. In caso di sovraccarico del metodo, questi due tipi sono stati utilizzati senza problemi. Con l'avvento dell'imballaggio/disimballaggio automatico, questo è diventato più difficile. Un esempio di ciò è il metodo sovraccaricato
remove()
in
ArrayList
. La classe
ArrayList
ha due metodi delete:
remove(index)
e
remove(object)
. In questo caso non si verificherà l'overload del metodo e il metodo corrispondente verrà chiamato con i parametri appropriati.
Conclusione
L'autoboxing è un meccanismo per convertire implicitamente i tipi di dati primitivi nelle corrispondenti classi wrapper (oggetti). Il compilatore utilizza il metodo
valueOf()
per convertire i tipi primitivi in oggetti e i metodi
IntValue()
,
doubleValue()
ecc., per ottenere i tipi primitivi dell'oggetto. L'autoboxing converte il tipo booleano
boolean
in booleano,
byte
in byte,
char
in carattere, in virgola
float
mobile , in intero, in lungo, in breve. Il disimballaggio avviene nella direzione opposta.
Articolo originaleint
long
short
GO TO FULL VERSION