La parola chiave final, che abbiamo visto nell’esempio della classe CCerchio in una lezione precedente, può essere utilizzata in vari contesti. Il caso più semplice è quello della dichiarazione di un attributo costante:
static final double PI = 3.141592
in questo caso viene dichiarata una variabile di classe di nome PI ( nel caso di valori costanti è utile inserire nomi tutti maiuscoli ) con il valore costante del pi greco ed ogni tentativo di modifica del valore produrrà un errore di compilazione.
Nell’uso come prefisso di una classe, come ad esempio:
final class CCerchio…
significa che non potranno essere derivate sottoclassi ( che studieremo nelle lezioni future ) da questa.
Nell’uso invece di dichiarazione di un metodo all’interno di una classe, come ad esempio:
…
final void GetName() {}
…
significa che il metodo non potrà essere ridefinito per eredietarietà. Questo va a vantaggio dell’efficienza perché il compilatore potrà effettuare delle ottimizzazioni che consentiranno una maggiore velocità di esecuzione, quindi è utile definire final nei metodi che vengono richiamati molte volte.
Il casting o conversione di tipo si rende necessario quando occorre trasformare un valore di un tipo in un altro tipo che abbiamo dichiarato in precedenza, il tutto deve essere fatto andando da tipi che occupano memo memoria a quelli che ne occupano di più. Facciamo un esempio:
…
byte b = 1;
int k = b;
…
In questo caso non abbiamo errore, perché si cerca di memorizzare il valore di un byte in una variabile dichiarata intera che è composta da 4 byte.
…
int k = 12;
byte b = k;
…
Ora abbiamo scritto l’inverso e vogliamo memorizzare il valore di una variabile di 4 byte in una di un solo byte, quindi il compilatore ci restituirà un errore. Insieme all’errore il compilatore ci avverte che se vogliamo questa conversione possiamo forzare con il cast esplicito ( explicit cast ), quindi dobbiamo scrivere:
…
int k = 12;
byte b = (byte)k;
…
In questo modo il compilatore ci lascia liberi di operare a nostro rischio e pericolo. In particolare in un byte si possono immagazzinare fino a 256 numeri ( 2 alla 8 dato che un byte è 8 bit ), ma se occupiamo un bit per il segno ( il bit ha valore 0 o 1 in formato binario ) avremo un range che va da -128 a +128 ( 2 alla 7 ).
// file Main.java package corso; public class Main { public static void main(String[] args) { int k = 200; byte b = (byte)k; System.out.println(b); } }
Se inserite un valore a k tra -127 e 127 va tutto bene, ma se ( come in questo caso ) ponete un numero maggiore, l’output sarà certamente diverso ( -56 in questo caso ), quindi attenzione!
Tutti gli esempi che abbiamo fatto finora sul casting tiravano in ballo solo tipi primitivi, ma lo stesso è possibile anche tra due oggetti a patto che appartengano a classi in relazione di ereditarietà. In particolare si effettua il casting di un oggetto di una sottoclasse in modo da ottenere un nuovo oggetto della superclasse. Da notare infine che non si possono effettuare conversioni da oggetti a tipi primitivi e viceversa.
<< Lezione Precedente – Inizio Corso – Lezione Successiva >>