1. Tipare
Variabilele de tipuri primitive (cu excepția tipului boolean
) sunt folosite pentru a stoca diferite tipuri de numere. Deși tipurile de variabile nu s-au schimbat niciodată, există un loc în care puteți converti de la un tip la altul. Și acel loc este o misiune .
Variabilele de diferite tipuri pot fi alocate între ele. Când faceți acest lucru, valoarea unei variabile de un tip este convertită într-o valoare de alt tip și atribuită celei de-a doua variabile. În acest sens, putem identifica două tipuri de conversie de tip: lărgire și îngustare.
Lărgirea este ca și cum ați muta o valoare de la un coș mic la unul mare: această operație este fără sudură și nedureroasă. Îngustarea are loc atunci când mutați o valoare dintr-un coș mare într-unul mic: s-ar putea să nu fie suficient spațiu și va trebui să aruncați ceva.
Iată tipurile, sortate după dimensiunea coșului:
2. Conversii de tip lărgire
Este adesea necesar să atribuiți o variabilă de un tip numeric unei variabile de alt tip numeric. Cum faci asta?
Java are 4 tipuri de numere întregi:
Tip | mărimea |
---|---|
byte |
1 byte |
short |
2 bytes |
int |
4 bytes |
long |
8 bytes |
Variabilele stocate în coșuri mai mici pot fi întotdeauna atribuite variabilelor stocate în coșuri mai mari.
int
, short
iar byte
variabilele pot fi atribuite cu ușurință long
variabilelor. short
iar byte
variabilele pot fi atribuite int
variabilelor. Și byte
variabilele pot fi atribuite short
variabilelor.
Exemple:
Cod | Descriere |
---|---|
|
Acest cod se va compila foarte bine. |
O astfel de conversie, de la un tip mai mic la unul mai mare, se numește conversie de tip lărgire .
Dar numerele reale?
Cu ei, totul este la fel - dimensiunea contează:
Tip | mărimea |
---|---|
float |
4 bytes |
double |
8 bytes |
float
variabilele pot fi alocate double
variabilelor fără probleme. Dar lucrurile sunt mai interesante cu tipurile întregi.
Puteți aloca orice variabilă întreagă unei float
variabile. Chiar și long
tipul, care are o lungime de 8 octeți. Și puteți aloca orice doriți - orice variabilă sau float
variabilă întreagă - unei double
variabile:
Cod | Notă |
---|---|
|
|
Rețineți că conversia la un tip real poate duce la pierderea preciziei din cauza lipsei de cifre semnificative suficiente.
La conversia de la numere întregi la numere în virgulă mobilă, părțile de ordin inferior ale numerelor pot fi eliminate. Dar, deoarece se înțelege că numerele fracționale stochează valori aproximative, astfel de operațiuni de atribuire sunt permise.
3. Îngustarea conversiilor de tip
Dar celelalte posibilități? Ce se întâmplă dacă trebuie să atribui o long
valoare unei int
variabile?
Imaginați-vă o variabilă ca un coș. Avem coșuri de diferite dimensiuni: 1, 2, 4 și 8 octeți. Nu este o problemă să transferi merele dintr-un coș mai mic într-unul mai mare. Dar atunci când treceți de la un coș mai mare la unul mai mic, unele dintre mere se pot pierde.
Această transformare - de la un tip mai mare la un tip mai mic - se numește conversie de tip îngustare . Când se efectuează o operație de atribuire ca aceasta, o parte dintr-un număr poate pur și simplu să nu se încadreze în noua variabilă și, prin urmare, poate fi aruncată.
Când restrângem un tip, trebuie să spunem în mod explicit compilatorului că nu facem o greșeală, că aruncăm în mod deliberat o parte din număr. Operatorul typecast este utilizat pentru aceasta. Este un nume de tip între paranteze .
În astfel de situații, compilatorul Java solicită programatorului să specifice operatorul typecast. În general, arată astfel:
(type) expression
Exemple:
Cod | Descriere |
---|---|
|
De fiecare dată operatorul typecast trebuie indicat în mod explicit |
Aici a
este egal cu 1
, și poate că operatorul typecast pare exagerat. Dar dacă ar a
fi mai mare?
Cod | Descriere |
---|---|
|
|
Un milion se potrivește perfect într-un long
și într-un int
. Dar atunci când se atribuie un milion unei short
variabile, primii doi octeți sunt eliminați și doar ultimii doi octeți sunt reținuți. Și când se atribuie unui byte
, singurul lucru care rămâne este ultimul octet.
Cum sunt aranjate numerele în memorie:
Tip | Notație binară | Notație zecimală |
---|---|---|
int |
0b 00000000 00001111 01000010 01000000 | 1000000 |
short |
0b 01000010 01000000 | 16.960 |
byte |
0b 01000000 | 64 |
char
tip
A char
, ca și a short
, ocupă doi octeți, dar pentru a converti unul în altul, trebuie întotdeauna să utilizați un operator de tipar. Problema aici este că short
tipul este semnat și poate conține valori de la -32,768
până la +32,767
, dar char
tipul este nesemnat și poate conține valori de la 0
până la 65,535
.
Numerele negative nu pot fi stocate într-un char
, dar pot fi stocate într-un short
. Și a short
nu poate stoca numere mai mari decât 32,767
, dar astfel de numere pot fi stocate într-un char
.
4. Tipul unei expresii
Ce se întâmplă dacă în aceeași expresie sunt folosite variabile de diferite tipuri? În mod logic, înțelegem că mai întâi trebuie convertite într-un tip comun. Dar care?
La cel mai mare, desigur.
Java se convertește întotdeauna la tipul mai mare. În linii mari, unul de tip este mai întâi lărgit și abia apoi operația se realizează folosind valori de același tip.
Dacă an int
și a long
sunt implicați într-o expresie, valoarea lui int
va fi convertită în a long
și numai atunci operația va continua:
Cod | Descriere |
---|---|
|
a va fi lărgit la a long și apoi va avea loc adăugarea. |
Numere în virgulă mobilă
Dacă într-o expresie sunt implicate un număr întreg și un număr în virgulă mobilă ( float
sau double
), întregul va fi convertit într-un număr în virgulă mobilă ( float
sau double
) și numai atunci operația va fi efectuată.
Dacă operația implică a float
și a double
, atunci float
va fi convertit în a double
. Ceea ce de fapt este de așteptat.
Tipurile byte
, short
, și char
sunt întotdeauna convertite în int
când interacționează unul cu celălalt. Există un motiv bun pentru care int
tipul este considerat tipul întreg standard.
Dacă înmulțiți a byte
cu a short
, obțineți un int
. Dacă înmulțiți a byte
cu a byte
, obțineți un int
. Chiar dacă adăugați a byte
și a byte
, obțineți un int
.
Există mai multe motive pentru aceasta. Exemple:
Cod | Descriere |
---|---|
|
110 * 120 este 13,200 , care este puțin mai mare decât valoarea maximă a byte tipului:127 |
|
110 + 120 este 230 , care este, de asemenea, puțin mai mare decât valoarea maximă a byte tipului:127 |
În general, atunci când înmulțim un număr de 8 biți (1 octet) cu un număr de 8 biți (1 octet), obținem un număr care ocupă biți de 16 biți (2 octeți)
Ca rezultat, toate operațiile cu tipuri întregi care sunt mai mici decât int
sunt întotdeauna convertite imediat în int
s. Și asta înseamnă că, dacă doriți să stocați rezultatul calculului într-o variabilă de tip mai mică decât un int
, atunci va trebui întotdeauna să specificați în mod explicit operatorul typecast.
Exemple:
Cod | Descriere |
---|---|
|
Expresia byte * byte va fi anint |
|
Expresia byte + byte va fi anint |
|
Expresia byte + int va fi o int Cea literală este o int . |
5. O nuanță importantă
Operatorul typecast are o prioritate destul de mare.
Aceasta înseamnă că, dacă o expresie conține, de exemplu, adăugare și un operator de tipare, tipare va fi efectuată înainte de adăugare.
Exemplu:
Cod | Descriere |
---|---|
|
Operatorul typecast va fi aplicat numai variabilei a , care este deja un byte . Acest cod nu se va compila. |
|
Acesta este modul corect. |
Dacă doriți să convertiți întreaga expresie într-un anumit tip, și nu doar o componentă a expresiei, atunci includeți întreaga expresie în paranteze și puneți operatorul typecast în față.
GO TO FULL VERSION