In Java sono presenti alcune agevolazioni sintattiche il cui scopo è evitare di scrivere parti di codice ripetitive e poco utili.
La prima di queste agevolazioni è utilizzata dal 100% degli sviluppatori Java. Si tratta dell'autoboxing, presente dalla versione 5 di Java, che permette di usare in maniera intercambiabile tipi primitivi (int, long,...) e le rispettive wrapper class (Integer, Long,...). La seconda, utilizzata spesso in maniera implicita, è detta widening, ed è presente fin dalla prima versione di Java.
L'uso di combinato di questi due meccanismi può talvolta avere effetti curiosi e un po' subdoli.
Cosa accade - ad esempio - se scriviamo il metodo:
public static void doSomething(Long l) {...}
e poi lo invochiamo così:
public static void main(String[] args) { byte b = 42; doSomething(b); }
Accade che il compilatore segnala un errore, per l'impossibilità di fare prima il widening poi l'autoboxing della variabile byte.
Cosa accade invece se il metodo doSomething viene scritto così
public static void doSomething(Object obj){...} e lo invochiamo usando lo stesso main visto in precedenza?
La risposta è che in questo caso il codice compila regolarmente.
Perché accade questo? Vediamo i passi uno ad uno:
1 - Il byte viene convertito in Byte (autoboxing)
2 - Il Byte viene utilizzato per widening come un Object dal metodo doSomething.
Volendo ottenere nuovamente il byte di origine si può fare un cast dentro il corpo di doSomething: Byte b = (Byte)obj, perché il widending ha comunque un riferimento ad un oggetto che di fatto è un Byte.
Sembra naturale, no?
Allora perché nel primo caso il codice non compila?
La risposta è nella linea di ereditarietà delle wrapper class. Prima viene fatto l'autoboxing da byte a Byte e poi si cerca di fare il widening verso Long, ma il widening fra oggetti funziona solo se esiste un legame di ereditarietà tra gli oggetti coinvolti: Long non ha legami con Byte, quindi non lo si può passare al metodo; al contrario Byte deriva da Object, quindi il codice compila regolarmente.
Niente di complesso, insomma, ma semplicemente qualcosa a cui fare attenzione quando si scrive il codice.
Riassumendo:
NON si può fare il widening da una wrapper class all'altra come di farebbe coi tipi primitivi
NON si può fare in sequenza il widening e poi il boxing
(un int non potrà mai divenire un Long)
RispondiEliminaalways i used to read smaller articles or reviews that as well clear their motive, and that is also happening with this article which I am reading at this place. itunes login account