CodeGym/Java Blog/Random-IT/Ampliamento e restringimento dei tipi primitivi
John Squirrels
Livello 41
San Francisco

Ampliamento e restringimento dei tipi primitivi

Pubblicato nel gruppo Random-IT
membri
CIAO! Man mano che avanzi in CodeGym, ti sei imbattuto in tipi primitivi molte volte. Ecco un breve elenco di ciò che sappiamo su di loro:
  1. Non sono oggetti e rappresentano un valore memorizzato
  2. Ci sono diversi tipi
    • Numeri interi: byte , short , int , long
    • Numeri in virgola mobile (frazionari): float e double
    • Valori logici: booleani
    • Valori simbolici (per rappresentare lettere e numeri): char
  3. Ogni tipo ha il proprio intervallo di valori:

Tipo primitivo Dimensioni in memoria Intervallo di valori
byte 8 bit -128 a 127
corto 16 bit -32768 a 32767
char 16 bit da 0 a 65536
int 32 bit Da -2147483648 a 2147483647
lungo 64 bit -9223372036854775808 a 9223372036854775807
galleggiante 32 bit (2 elevato a -149) a ((2 - (2 elevato a -23)) * 2 elevato a 127)
Doppio 64 bit (-2 elevato a 63) a ((2 elevato a 63) - 1)
booleano 8 (se utilizzato negli array), 32 (se non utilizzato negli array) vero o falso
Ma oltre ad avere valori diversi, differiscono anche per quanto spazio occupano nella memoria. Un int occupa più di un byte. E un lungo è più grande di uno corto. La quantità di memoria occupata dai primitivi può essere paragonata alle matrioske russe: Ampliamento e restringimento dei tipi primitivi - 2 ogni matrioska ha spazio disponibile all'interno. Più grande è la bambola da nidificazione, più spazio c'è. Una grande bambola da nidificazione ( lunga ) ospiterà facilmente una bambola più piccola . Si adatta facilmente e non è necessario fare nient'altro. In Java, quando si lavora con le primitive, si parla di conversione implicita. In altre parole, si chiama allargamento.

Ampliamento in Java

Ecco un semplice esempio di conversione di ampliamento:
public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       byte littleNumber = 16;

       bigNumber = littleNumber;
       System.out.println(bigNumber);
   }
}
Qui assegniamo un valore in byte a una variabile int . L'assegnazione riesce senza problemi: il valore memorizzato in un byte occupa meno memoria di quella che un int può ospitare. La piccola bambola da nidificazione (valore in byte) si adatta facilmente alla grande bambola da nidificazione ( variabile int ). È una questione diversa se si tenta di fare il contrario, ovvero inserire un valore elevato in una variabile il cui intervallo non può contenere un tipo di dati così grande. Con vere bambole nidificanti, il numero semplicemente non si adatterebbe. Con Java, può, ma con sfumature. Proviamo a inserire un int in una variabile breve :
public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = bigNumber;// Error!
   System.out.println(bigNumber);
}
Errore! Il compilatore capisce che stai cercando di fare qualcosa di anormale spingendo una grande bambola da nidificazione ( int ) all'interno di una piccola ( short ). In questo caso, l'errore di compilazione è un avviso del compilatore: "Ehi, sei assolutamente sicuro di volerlo fare?" Se sei sicuro, allora dici al compilatore: "Va tutto bene. So cosa sto facendo!" Questo processo è chiamato conversione esplicita del tipo o restringimento.

Restringimento in Java

Per eseguire una conversione di restringimento, è necessario indicare esplicitamente il tipo in cui si desidera convertire il valore. In altre parole, devi rispondere alla domanda del compilatore: "Bene, in quale di queste piccole bambole da nidificazione vuoi mettere questa grande bambola da nidificazione?" Nel nostro caso, assomiglia a questo:
public static void main(String[] args) {

   int bigNumber = 10000000;

   short littleNumber = 1000;

   littleNumber = (short) bigNumber;
   System.out.println(littleNumber);
}
Indichiamo esplicitamente che vogliamo inserire un int in una variabile short e che ci assumeremo la responsabilità. Visto che è stato esplicitamente indicato un tipo più ristretto, il compilatore esegue la conversione. Qual è il risultato? Output della console: -27008 È stato un po' inaspettato. Perché l'abbiamo capito esattamente? In effetti, è tutto molto semplice. Originariamente, il valore era 10000000. Era memorizzato in una variabile int , che occupa 32 bit. Questa è la sua rappresentazione binaria:
Ampliamento e restringimento dei tipi primitivi - 3
Scriviamo questo valore in una variabile breve , che può memorizzare solo 16 bit! Di conseguenza, solo i primi 16 bit del nostro numero verranno spostati lì. Il resto verrà scartato. Di conseguenza, la variabile breve riceve il seguente valore
Ampliamento e restringimento dei tipi primitivi - 4
che in forma decimale è uguale a -27008 Ecco perché il compilatore chiede di "confermare" indicando una conversione di restringimento esplicita a un tipo specifico. Innanzitutto, questo dimostra che ti stai assumendo la responsabilità del risultato. E in secondo luogo, dice al compilatore quanto spazio allocare quando avviene la conversione. Dopotutto, nell'ultimo esempio, se assegnassimo un valore int a una variabile byte anziché short , allora avremmo a disposizione solo 8 bit, non 16, e il risultato sarebbe diverso. I tipi frazionari ( float e double ) hanno il proprio processo per restringere le conversioni. Se provi a trasmettere un numero di fazione a un tipo intero, la parte frazionaria verrà scartata.
public static void main(String[] args) {

   double d = 2.7;

   long x = (int) d;
   System.out.println(x);
}
Uscita console: 2

char

Sai già che char viene utilizzato per visualizzare singoli caratteri.
public static void main(String[] args) {

   char c = '!';
   char z = 'z';
   char i = '8';

}
Ma questo tipo di dati ha diverse caratteristiche che è importante comprendere. Diamo un'altra occhiata alla tabella degli intervalli di valori:
Tipo primitivo Dimensioni in memoria Intervallo di valori
byte 8 bit -128 a 127
corto 16 bit -32768 a 32767
char 16 bit da 0 a 65536
int 32 bit Da -2147483648 a 2147483647
lungo 64 bit -9223372036854775808 a 9223372036854775807
galleggiante 32 bit (2 elevato a -149) a ((2 - (2 elevato a -23)) * 2 elevato a 127)
Doppio 64 bit (-2 elevato a 63) a ((2 elevato a 63) - 1)
booleano 8 (se utilizzato negli array), 32 (se non utilizzato negli array) vero o falso
L'intervallo da 0 a 65536 è indicato per il tipo di carattere . Ma cosa significa? Dopotutto, un carattere non rappresenta solo numeri, ma anche lettere, segni di punteggiatura... Il fatto è che in Java i valori dei caratteri sono memorizzati in formato Unicode. Abbiamo già incontrato Unicode in una delle lezioni precedenti. Probabilmente ricorderai che Unicode è uno standard di codifica dei caratteri che include i simboli di quasi tutte le lingue scritte del mondo. In altre parole, è un elenco di codici speciali che rappresentano quasi ogni carattere in qualsiasi lingua. L'intera tabella Unicode è molto grande e, ovviamente, non è necessario impararla a memoria. Eccone una piccola parte: Ampliamento e restringimento dei tipi primitivi - 5 La cosa principale è capire come vengono memorizzati i caratteri e ricordare che se conosci il codice di un particolare carattere, puoi sempre produrre quel carattere nel tuo programma. Proviamo con un numero casuale:
public static void main(String[] args) {

   int x = 32816;

   char c = (char) x ;
   System.out.println(c);
}
Output della console: 耰 Questo è il formato utilizzato per memorizzare i caratteri in Java. Ogni simbolo corrisponde a un numero: un codice numerico a 16 bit (due byte). In Unicode, 32816 corrisponde al carattere cinese 耰. Prendere nota del seguente punto. In questo esempio, abbiamo utilizzato una variabile int . Occupa 32 bit in memoria, mentre un carattere ne occupa 16. Qui abbiamo scelto un int , perché il nostro numero (32816) non starebbe in un short . Sebbene la dimensione di un carattere (proprio come un short ) sia di 16 bit, non ci sono numeri negativi nell'intervallo di caratteri , quindi la parte "positiva" del caratterela portata è doppia (65536 invece di 32767 per il tipo corto ). Possiamo usare un int fintanto che il nostro codice rimane al di sotto di 65536. Ma se crei un valore int maggiore di 65536, occuperà più di 16 bit. E questo si tradurrà in una conversione restringente
char c = (char) x;
i bit extra verranno scartati (come discusso sopra) e il risultato sarà del tutto inaspettato.

Funzioni speciali dell'aggiunta di caratteri e numeri interi

Facciamo un esempio insolito:
public class Main {

   public static void main(String[] args) {

      char c = '1';

      int i = 1;

       System.out.println(i + c);
   }
}
Uscita console: 50 O_О Che senso ha? 1+1. Da dove vengono i 50?! Sai già che chari valori sono archiviati in memoria come numeri nell'intervallo da 0 a 65536 e che questi numeri sono una rappresentazione Unicode di un carattere. Ampliamento e restringimento dei tipi primitivi - 6 Quando aggiungiamo un carattere e un tipo di numero intero, il carattere viene convertito nel numero Unicode corrispondente. Nel nostro codice, quando abbiamo aggiunto 1 e '1', il simbolo '1' è stato convertito nel proprio codice, che è 49 (puoi verificarlo nella tabella sopra). Pertanto, il risultato è 50. Prendiamo ancora una volta il nostro vecchio amico 耰 come esempio e proviamo ad aggiungerlo a un numero.
public static void main(String[] args) {

   char c = '耰';
   int x = 200;

   System.out.println(c + x);
}
Output della console: 33016 Abbiamo già scoperto che 耰 corrisponde a 32816. E quando aggiungiamo questo numero e 200, otteniamo il nostro risultato: 33016. :) Come puoi vedere, l'algoritmo qui è abbastanza semplice, ma non dovresti dimenticarlo .
Commenti
  • Popolari
  • Nuovi
  • Vecchi
Devi avere effettuato l'accesso per lasciare un commento
Questa pagina non ha ancora commenti